home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games Extra 1996 September / Amiga Games Extra CD-ROM 9-1996.iso / userbox / publicdomain / vim-4.2 / src / term.c < prev    next >
C/C++ Source or Header  |  1996-06-16  |  73KB  |  3,107 lines

  1. /* vi:set ts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8. /*
  9.  *
  10.  * term.c: functions for controlling the terminal
  11.  *
  12.  * primitive termcap support for Amiga, MSDOS, and Win32 included
  13.  *
  14.  * NOTE: padding and variable substitution is not performed,
  15.  * when compiling without HAVE_TGETENT, we use tputs() and tgoto() dummies.
  16.  */
  17.  
  18. /*
  19.  * Some systems have a prototype for tgetstr() with (char *) instead of
  20.  * (char **). This define removes that prototype. We include our own prototype
  21.  * below.
  22.  */
  23.  
  24. #define tgetstr tgetstr_defined_wrong
  25. #include "vim.h"
  26.  
  27. #include "globals.h"
  28. #include "option.h"
  29. #include "proto.h"
  30.  
  31. #ifdef HAVE_TGETENT
  32. # ifdef HAVE_TERMCAP_H
  33. #  include <termcap.h>
  34. # endif
  35.  
  36. /*
  37.  * A few linux systems define outfuntype in termcap.h to be used as the third
  38.  * argument for tputs().
  39.  */
  40. # ifdef VMS
  41. #  define TPUTSFUNCAST
  42. # else
  43. #  ifdef HAVE_OUTFUNTYPE
  44. #   define TPUTSFUNCAST (outfuntype)
  45. #  else
  46. #   define TPUTSFUNCAST (int (*)())
  47. #  endif
  48. # endif
  49. #endif
  50.  
  51. #undef tgetstr
  52.  
  53. /*
  54.  * Here are the builtin termcap entries.  They are not stored as complete
  55.  * Tcarr structures, as such a structure is too big.
  56.  *
  57.  * The entries are compact, therefore they normally are included even when
  58.  * HAVE_TGETENT is defined.    When HAVE_TGETENT is defined, the builtin entries
  59.  * can be accessed with "builtin_amiga", "builtin_ansi", "builtin_debug", etc.
  60.  *
  61.  * Each termcap is a list of builtin_term structures. It always starts with
  62.  * KS_NAME, which separates the entries.  See parse_builtin_tcap() for all
  63.  * details.
  64.  * bt_entry is either a KS_xxx code (< 0x100), or a K_xxx code.
  65.  */
  66. struct builtin_term
  67. {
  68.     int            bt_entry;
  69.     char        *bt_string;
  70. };
  71.  
  72. /* start of keys that are not directly used by Vim but can be mapped */
  73. #define BT_EXTRA_KEYS    0x101
  74.  
  75. static struct builtin_term *find_builtin_term __ARGS((char_u *name));
  76. static void parse_builtin_tcap __ARGS((char_u *s));
  77. static void gather_termleader __ARGS((void));
  78. static int get_bytes_from_buf __ARGS((char_u *, char_u *, int));
  79. static int is_builtin_term __ARGS((char_u *));
  80.  
  81. #ifdef HAVE_TGETENT
  82. static char_u *tgetent_error __ARGS((char_u *, char_u *));
  83.  
  84. /*
  85.  * Here is our own prototype for tgetstr(), any prototypes from the include
  86.  * files have been disabled by the define at the start of this file.
  87.  */
  88. char            *tgetstr __PARMS((char *, char **));
  89.  
  90. /*
  91.  * Don't declare these variables if termcap.h contains them.
  92.  * Autoconf checks if these variables should be declared extern (not all
  93.  * systems have them).
  94.  * Some versions define ospeed to be speed_t, but that is incompatible with
  95.  * BSD, where ospeed is short and speed_t is long.
  96.  */
  97. # ifndef HAVE_OSPEED
  98. #  ifdef OSPEED_EXTERN
  99. extern short ospeed;
  100. #   else
  101. short ospeed;
  102. #   endif
  103. # endif
  104. # ifndef HAVE_UP_BC_PC
  105. #  ifdef UP_BC_PC_EXTERN
  106. extern char *UP, *BC, PC;
  107. #  else
  108. char *UP, *BC, PC;
  109. #  endif
  110. # endif
  111.  
  112. # define TGETSTR(s, p)    (char_u *)tgetstr((s), (char **)(p))
  113. # define TGETENT(b, t)    tgetent((char *)(b), (char *)(t))
  114.  
  115. #endif /* HAVE_TGETENT */
  116.  
  117. struct builtin_term builtin_termcaps[] =
  118. {
  119.  
  120. #if defined(USE_GUI)
  121. /*
  122.  * Motif/Athena pseudo term-cap.
  123.  */
  124.     {KS_NAME,        "gui"},
  125.     {KS_CE,            "\033|$"},
  126.     {KS_AL,            "\033|i"},
  127. # ifdef TERMINFO
  128.     {KS_CAL,        "\033|%p1%dI"},
  129. # else
  130.     {KS_CAL,        "\033|%dI"},
  131. # endif
  132.     {KS_DL,            "\033|d"},
  133. # ifdef TERMINFO
  134.     {KS_CDL,        "\033|%p1%dD"},
  135.     {KS_CS,            "\033|%p1%d;%p2%dR"},
  136. # else
  137.     {KS_CDL,        "\033|%dD"},
  138.     {KS_CS,            "\033|%d;%dR"},
  139. # endif
  140.     {KS_CL,            "\033|C"},
  141.     {KS_ME,            "\033|63H"},    /* 63 = HL_ALL,            H = off */
  142.     {KS_MR,            "\033|1h"},        /* 1  = HL_INVERSE,        h = on */
  143.     {KS_MD,            "\033|2h"},        /* 2  = HL_BOLD,        h = on */
  144.     {KS_SE,            "\033|16H"},    /* 16 = HL_STANDOUT,    H = off */
  145.     {KS_SO,            "\033|16h"},    /* 16 = HL_STANDOUT,    h = on */
  146.     {KS_UE,            "\033|8H"},        /* 8  = HL_UNDERLINE,    H = off */
  147.     {KS_US,            "\033|8h"},        /* 8  = HL_UNDERLINE,    h = on */
  148.     {KS_CZR,        "\033|4H"},        /* 4  = HL_ITAL,        H = off */
  149.     {KS_CZH,        "\033|4h"},        /* 4  = HL_ITAL,        h = on */
  150.     {KS_VB,            "\033|f"},
  151. # ifdef TERMINFO
  152.     {KS_CM,            "\033|%p1%d;%p2%dM"},
  153. # else
  154.     {KS_CM,            "\033|%d;%dM"},
  155. # endif
  156.         /* there are no key sequences here, the GUI sequences are recognized
  157.          * in check_termcodes() */
  158. #endif
  159.  
  160. #ifndef NO_BUILTIN_TCAPS
  161.  
  162. # if defined(AMIGA) || defined(ALL_BUILTIN_TCAPS)
  163. /*
  164.  * Amiga console window, default for Amiga
  165.  */
  166.     {KS_NAME,        "amiga"},
  167.     {KS_CE,            "\033[K"},
  168.     {KS_CD,            "\033[J"},
  169.     {KS_AL,            "\033[L"},
  170. #  ifdef TERMINFO
  171.     {KS_CAL,        "\033[%p1%dL"},
  172. #  else
  173.     {KS_CAL,        "\033[%dL"},
  174. #  endif
  175.     {KS_DL,            "\033[M"},
  176. #  ifdef TERMINFO
  177.     {KS_CDL,        "\033[%p1%dM"},
  178. #  else
  179.     {KS_CDL,        "\033[%dM"},
  180. #  endif
  181.     {KS_CL,            "\014"},
  182.     {KS_VI,            "\033[0 p"},
  183.     {KS_VE,            "\033[1 p"},
  184.     {KS_ME,            "\033[0m"},
  185.     {KS_MR,            "\033[7m"},
  186.     {KS_MD,            "\033[1m"},
  187.     {KS_SE,            "\033[0m"},
  188.     {KS_SO,            "\033[33m"},
  189.     {KS_US,            "\033[4m"},
  190.     {KS_UE,            "\033[0m"},
  191.     {KS_CZH,        "\033[3m"},
  192.     {KS_CZR,        "\033[0m"},
  193.     {KS_MS,            "\001"},
  194. #  ifdef TERMINFO
  195.     {KS_CM,            "\033[%i%p1%d;%p2%dH"},
  196. #  else
  197.     {KS_CM,            "\033[%i%d;%dH"},
  198. #  endif
  199. #  ifdef TERMINFO
  200.     {KS_CRI,        "\033[%p1%dC"},
  201. #  else
  202.     {KS_CRI,        "\033[%dC"},
  203. #  endif
  204.     {K_UP,            "\233A"},
  205.     {K_DOWN,        "\233B"},
  206.     {K_LEFT,        "\233D"},
  207.     {K_RIGHT,        "\233C"},
  208.     {K_S_UP,        "\233T"},
  209.     {K_S_DOWN,        "\233S"},
  210.     {K_S_LEFT,        "\233 A"},
  211.     {K_S_RIGHT,        "\233 @"},
  212.     {K_S_TAB,        "\233Z"},
  213.     {K_F1,            "\233\060~"},/* some compilers don't understand "\2330" */
  214.     {K_F2,            "\233\061~"},
  215.     {K_F3,            "\233\062~"},
  216.     {K_F4,            "\233\063~"},
  217.     {K_F5,            "\233\064~"},
  218.     {K_F6,            "\233\065~"},
  219.     {K_F7,            "\233\066~"},
  220.     {K_F8,            "\233\067~"},
  221.     {K_F9,            "\233\070~"},
  222.     {K_F10,            "\233\071~"},
  223.     {K_S_F1,        "\233\061\060~"},
  224.     {K_S_F2,        "\233\061\061~"},
  225.     {K_S_F3,        "\233\061\062~"},
  226.     {K_S_F4,        "\233\061\063~"},
  227.     {K_S_F5,        "\233\061\064~"},
  228.     {K_S_F6,        "\233\061\065~"},
  229.     {K_S_F7,        "\233\061\066~"},
  230.     {K_S_F8,        "\233\061\067~"},
  231.     {K_S_F9,        "\233\061\070~"},
  232.     {K_S_F10,        "\233\061\071~"},
  233.     {K_HELP,        "\233?~"},
  234.     {K_INS,            "\233\064\060~"},    /* 101 key keyboard */
  235.     {K_PAGEUP,        "\233\064\061~"},    /* 101 key keyboard */
  236.     {K_PAGEDOWN,    "\233\064\062~"},    /* 101 key keyboard */
  237.     {K_HOME,        "\233\064\064~"},    /* 101 key keyboard */
  238.     {K_END,            "\233\064\065~"},    /* 101 key keyboard */
  239.  
  240.     {BT_EXTRA_KEYS,    ""},
  241.     {TERMCAP2KEY('#', '2'),    "\233\065\064~"},    /* shifted home key */
  242.     {TERMCAP2KEY('#', '3'),    "\233\065\060~"},    /* shifted insert key */
  243.     {TERMCAP2KEY('*', '7'),    "\233\065\065~"},    /* shifted end key */
  244. # endif
  245.  
  246. # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) || defined(__EMX__)
  247. /*
  248.  * standard ANSI terminal, default for unix
  249.  */
  250.     {KS_NAME,        "ansi"},
  251.     {KS_CE,            "\033[K"},
  252.     {KS_AL,            "\033[L"},
  253. #  ifdef TERMINFO
  254.     {KS_CAL,        "\033[%p1%dL"},
  255. #  else
  256.     {KS_CAL,        "\033[%dL"},
  257. #  endif
  258.     {KS_DL,            "\033[M"},
  259. #  ifdef TERMINFO
  260.     {KS_CDL,        "\033[%p1%dM"},
  261. #  else
  262.     {KS_CDL,        "\033[%dM"},
  263. #  endif
  264.     {KS_CL,            "\033[H\033[2J"},
  265.     {KS_ME,            "\033[0m"},
  266.     {KS_MR,            "\033[7m"},
  267.     {KS_MS,            "\001"},
  268. #  ifdef TERMINFO
  269.     {KS_CM,            "\033[%i%p1%d;%p2%dH"},
  270. #  else
  271.     {KS_CM,            "\033[%i%d;%dH"},
  272. #  endif
  273. #  ifdef TERMINFO
  274.     {KS_CRI,        "\033[%p1%dC"},
  275. #  else
  276.     {KS_CRI,        "\033[%dC"},
  277. #  endif
  278. # endif
  279.  
  280. # if defined(MSDOS) || defined(ALL_BUILTIN_TCAPS) || defined(__EMX__)
  281. /*
  282.  * These codes are valid when nansi.sys or equivalent has been installed.
  283.  * Function keys on a PC are preceded with a NUL. These are converted into
  284.  * K_NUL '\316' in mch_inchar(), because we cannot handle NULs in key codes.
  285.  * CTRL-arrow is used instead of SHIFT-arrow.
  286.  */
  287. #ifdef __EMX__
  288.     {KS_NAME,        "os2ansi"},
  289. #else
  290.     {KS_NAME,        "pcansi"},
  291.     {KS_DL,            "\033[M"},
  292.     {KS_AL,            "\033[L"},
  293. #endif
  294.     {KS_CE,            "\033[K"},
  295.     {KS_CL,            "\033[2J"},
  296.     {KS_ME,            "\033[0m"},
  297.     {KS_MR,            "\033[7m"},
  298.     {KS_MS,            "\001"},
  299. #  ifdef TERMINFO
  300.     {KS_CM,            "\033[%i%p1%d;%p2%dH"},
  301. #  else
  302.     {KS_CM,            "\033[%i%d;%dH"},
  303. #  endif
  304. #  ifdef TERMINFO
  305.     {KS_CRI,        "\033[%p1%dC"},
  306. #  else
  307.     {KS_CRI,        "\033[%dC"},
  308. #  endif
  309.     {K_UP,            "\316H"},
  310.     {K_DOWN,        "\316P"},
  311.     {K_LEFT,        "\316K"},
  312.     {K_RIGHT,        "\316M"},
  313.     {K_S_LEFT,        "\316s"},
  314.     {K_S_RIGHT,        "\316t"},
  315.     {K_F1,            "\316;"},
  316.     {K_F2,            "\316<"},
  317.     {K_F3,            "\316="},
  318.     {K_F4,            "\316>"},
  319.     {K_F5,            "\316?"},
  320.     {K_F6,            "\316@"},
  321.     {K_F7,            "\316A"},
  322.     {K_F8,            "\316B"},
  323.     {K_F9,            "\316C"},
  324.     {K_F10,            "\316D"},
  325.     {K_F11,            "\316\205"},    /* guessed */
  326.     {K_F12,            "\316\206"},    /* guessed */
  327.     {K_S_F1,        "\316T"},
  328.     {K_S_F2,        "\316U"},
  329.     {K_S_F3,        "\316V"},
  330.     {K_S_F4,        "\316W"},
  331.     {K_S_F5,        "\316X"},
  332.     {K_S_F6,        "\316Y"},
  333.     {K_S_F7,        "\316Z"},
  334.     {K_S_F8,        "\316["},
  335.     {K_S_F9,        "\316\\"},
  336.     {K_S_F10,        "\316]"},
  337.     {K_S_F11,        "\316\207"},    /* guessed */
  338.     {K_S_F12,        "\316\210"},    /* guessed */
  339.     {K_INS,            "\316R"},
  340.     {K_DEL,            "\316S"},
  341.     {K_HOME,        "\316G"},
  342.     {K_END,            "\316O"},
  343.     {K_PAGEDOWN,    "\316Q"},
  344.     {K_PAGEUP,        "\316I"},
  345. # endif
  346.  
  347. # if defined(MSDOS)
  348. /*
  349.  * These codes are valid for the pc video.    The entries that start with ESC |
  350.  * are translated into conio calls in msdos.c. Default for MSDOS.
  351.  */
  352.     {KS_NAME,        "pcterm"},
  353.     {KS_CE,            "\033|K"},
  354.     {KS_AL,            "\033|L"},
  355.     {KS_DL,            "\033|M"},
  356. #  ifdef TERMINFO
  357.     {KS_CS,            "\033|%i%p1%d;%p2%dr"},
  358. #  else
  359.     {KS_CS,            "\033|%i%d;%dr"},
  360. #  endif
  361.     {KS_CL,            "\033|J"},
  362.     {KS_ME,            "\033|0m"},
  363.     {KS_MR,            "\033|112m"},
  364.     {KS_MD,            "\033|63m"},
  365.     {KS_SE,            "\033|0m"},
  366.     {KS_SO,            "\033|31m"},
  367.     {KS_MS,            "\001"},
  368. #  ifdef TERMINFO
  369.     {KS_CM,            "\033|%i%p1%d;%p2%dH"},
  370. #  else
  371.     {KS_CM,            "\033|%i%d;%dH"},
  372. #  endif
  373.     {K_UP,            "\316H"},
  374.     {K_DOWN,        "\316P"},
  375.     {K_LEFT,        "\316K"},
  376.     {K_RIGHT,        "\316M"},
  377.     {K_S_LEFT,        "\316s"},
  378.     {K_S_RIGHT,        "\316t"},
  379.     {K_S_TAB,        "\316\017"},
  380.     {K_F1,            "\316;"},
  381.     {K_F2,            "\316<"},
  382.     {K_F3,            "\316="},
  383.     {K_F4,            "\316>"},
  384.     {K_F5,            "\316?"},
  385.     {K_F6,            "\316@"},
  386.     {K_F7,            "\316A"},
  387.     {K_F8,            "\316B"},
  388.     {K_F9,            "\316C"},
  389.     {K_F10,            "\316D"},
  390.     {K_F11,            "\316\205"},    /* only when nobioskey */
  391.     {K_F12,            "\316\206"},    /* only when nobioskey */
  392.     {K_S_F1,        "\316T"},
  393.     {K_S_F2,        "\316U"},
  394.     {K_S_F3,        "\316V"},
  395.     {K_S_F4,        "\316W"},
  396.     {K_S_F5,        "\316X"},
  397.     {K_S_F6,        "\316Y"},
  398.     {K_S_F7,        "\316Z"},
  399.     {K_S_F8,        "\316["},
  400.     {K_S_F9,        "\316\\"},
  401.     {K_S_F10,        "\316]"},
  402.     {K_S_F11,        "\316\207"},    /* only when nobioskey */
  403.     {K_S_F12,        "\316\210"},    /* only when nobioskey */
  404.     {K_INS,            "\316R"},
  405.     {K_DEL,            "\316S"},
  406.     {K_HOME,        "\316G"},
  407.     {K_END,            "\316O"},
  408.     {K_PAGEDOWN,    "\316Q"},
  409.     {K_PAGEUP,        "\316I"},
  410. # endif
  411.  
  412. # if defined(WIN32) || defined(ALL_BUILTIN_TCAPS) || defined(__EMX__)
  413. /*
  414.  * These codes are valid for the Win32 Console .  The entries that start with
  415.  * ESC | are translated into console calls in win32.c.  The function keys
  416.  * are also translated in win32.c.
  417.  */
  418.     {KS_NAME,        "win32"},
  419.     {KS_CE,            "\033|K"},        /* clear to end of line */
  420.     {KS_AL,            "\033|L"},        /* add new blank line */
  421. #  ifdef TERMINFO
  422.     {KS_CAL,        "\033|%p1%dL"},    /* add number of new blank lines */
  423. #  else
  424.     {KS_CAL,        "\033|%dL"},    /* add number of new blank lines */
  425. #  endif
  426.     {KS_DL,            "\033|M"},        /* delete line */
  427. #  ifdef TERMINFO
  428.     {KS_CDL,        "\033|%p1%dM"},    /* delete number of lines */
  429. #  else
  430.     {KS_CDL,        "\033|%dM"},    /* delete number of lines */
  431. #  endif
  432.     {KS_CL,            "\033|J"},        /* clear screen */
  433.     {KS_CD,            "\033|j"},        /* clear to end of display */
  434.     {KS_VI,            "\033|v"},        /* cursor invisible */
  435.     {KS_VE,            "\033|V"},        /* cursor visible */
  436.  
  437.     {KS_ME,            "\033|0m"},        /* normal mode */
  438.     {KS_MR,            "\033|112m"},    /* reverse mode: black text on lightgray */
  439.     {KS_MD,            "\033|63m"},    /* bold mode: white text on cyan */
  440. #if 1
  441.     {KS_SO,            "\033|31m"},    /* standout mode: white text on blue */
  442.     {KS_SE,            "\033|0m"},        /* standout mode end */
  443. #else
  444.     {KS_SO,            "\033|F"},        /* standout mode: high intensity text */
  445.     {KS_SE,            "\033|f"},        /* standout mode end */
  446. #endif
  447.     {KS_CZH,        "\033|225m"},    /* italic mode: blue text on yellow */
  448.     {KS_CZR,        "\033|0m"},        /* italic mode end */
  449.     {KS_US,            "\033|67m"},    /* underscore mode: cyan text on red */
  450.     {KS_UE,            "\033|0m"},        /* underscore mode end */
  451.  
  452.     {KS_MS,            "\001"},        /* save to move cur in reverse mode */
  453. #  ifdef TERMINFO
  454.     {KS_CM,            "\033|%i%p1%d;%p2%dH"},    /* cursor motion */
  455. #  else
  456.     {KS_CM,            "\033|%i%d;%dH"},        /* cursor motion */
  457. #  endif
  458.     {KS_VB,            "\033|B"},        /* visual bell */
  459.     {KS_TI,            "\033|S"},        /* put terminal in termcap mode */
  460.     {KS_TE,            "\033|E"},        /* out of termcap mode */
  461.     {KS_CS,         "\033|%i%d;%dr"},    /* scroll region */
  462.  
  463.     {K_UP,            "\316H"},
  464.     {K_DOWN,        "\316P"},
  465.     {K_LEFT,        "\316K"},
  466.     {K_RIGHT,        "\316M"},
  467.     {K_S_UP,        "\316\304"},
  468.     {K_S_DOWN,        "\316\317"},
  469.     {K_S_LEFT,        "\316\311"},
  470.     {K_S_RIGHT,        "\316\313"},
  471.     {K_S_TAB,        "\316\017"},
  472.     {K_F1,            "\316;"},
  473.     {K_F2,            "\316<"},
  474.     {K_F3,            "\316="},
  475.     {K_F4,            "\316>"},
  476.     {K_F5,            "\316?"},
  477.     {K_F6,            "\316@"},
  478.     {K_F7,            "\316A"},
  479.     {K_F8,            "\316B"},
  480.     {K_F9,            "\316C"},
  481.     {K_F10,            "\316D"},
  482.     {K_F11,            "\316\205"},
  483.     {K_F12,            "\316\206"},
  484.     {K_S_F1,        "\316T"},
  485.     {K_S_F2,        "\316U"},
  486.     {K_S_F3,        "\316V"},
  487.     {K_S_F4,        "\316W"},
  488.     {K_S_F5,        "\316X"},
  489.     {K_S_F6,        "\316Y"},
  490.     {K_S_F7,        "\316Z"},
  491.     {K_S_F8,        "\316["},
  492.     {K_S_F9,        "\316\\"},
  493.     {K_S_F10,        "\316]"},
  494.     {K_S_F11,        "\316\207"},
  495.     {K_S_F12,        "\316\210"},
  496.     {K_INS,            "\316R"},
  497.     {K_DEL,            "\316S"},
  498.     {K_HOME,        "\316G"},
  499.     {K_END,            "\316O"},
  500.     {K_PAGEDOWN,    "\316Q"},
  501.     {K_PAGEUP,        "\316I"},
  502. # endif
  503.  
  504. # if defined(ALL_BUILTIN_TCAPS) || defined(MINT)
  505. /*
  506.  * Ordinary vt52
  507.  */
  508.     {KS_NAME,         "vt52"},
  509.     {KS_CE,            "\033K"},
  510.     {KS_CD,            "\033J"},
  511.     {KS_CM,            "\033Y%+ %+ "},
  512. #  ifdef MINT
  513.     {KS_AL,            "\033L"},
  514.     {KS_DL,            "\033M"},
  515.     {KS_CL,            "\033E"},
  516.     {KS_SR,            "\033I"},
  517.     {KS_VE,            "\033e"},
  518.     {KS_VI,            "\033f"},
  519.     {KS_SO,            "\033p"},
  520.     {KS_SE,            "\033q"},
  521.     {K_UP,            "\033A"},
  522.     {K_DOWN,        "\033B"},
  523.     {K_LEFT,        "\033D"},
  524.     {K_RIGHT,        "\033C"},
  525.     {K_S_UP,        "\033a"},
  526.     {K_S_DOWN,        "\033b"},
  527.     {K_S_LEFT,        "\033d"},
  528.     {K_S_RIGHT,        "\033c"},
  529.     {K_F1,            "\033P"},
  530.     {K_F2,            "\033Q"},
  531.     {K_F3,            "\033R"},
  532.     {K_F4,            "\033S"},
  533.     {K_F5,            "\033T"},
  534.     {K_F6,            "\033U"},
  535.     {K_F7,            "\033V"},
  536.     {K_F8,            "\033W"},
  537.     {K_F9,            "\033X"},
  538.     {K_F10,            "\033Y"},
  539.     {K_S_F1,        "\033p"},
  540.     {K_S_F2,        "\033q"},
  541.     {K_S_F3,        "\033r"},
  542.     {K_S_F4,        "\033s"},
  543.     {K_S_F5,        "\033t"},
  544.     {K_S_F6,        "\033u"},
  545.     {K_S_F7,        "\033v"},
  546.     {K_S_F8,        "\033w"},
  547.     {K_S_F9,        "\033x"},
  548.     {K_S_F10,        "\033y"},
  549.     {K_INS,            "\033I"},
  550.     {K_HOME,        "\033E"},
  551.     {K_PAGEDOWN,    "\033b"},
  552.     {K_PAGEUP,        "\033a"},
  553. #  else
  554.     {KS_AL,            "\033T"},
  555.     {KS_DL,            "\033U"},
  556.     {KS_CL,            "\033H\033J"},
  557.     {KS_ME,            "\033SO"},
  558.     {KS_MR,            "\033S2"},
  559.     {KS_MS,            "\001"},
  560. #  endif
  561. # endif
  562.  
  563. # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS) || defined(__EMX__)
  564. /*
  565.  * The xterm termcap is missing F14 and F15, because they send the same
  566.  * codes as the undo and help key, although they don't work on all keyboards.
  567.  */
  568.     {KS_NAME,        "xterm"},
  569.     {KS_CE,            "\033[K"},
  570.     {KS_AL,            "\033[L"},
  571. #  ifdef TERMINFO
  572.     {KS_CAL,        "\033[%p1%dL"},
  573. #  else
  574.     {KS_CAL,        "\033[%dL"},
  575. #  endif
  576.     {KS_DL,            "\033[M"},
  577. #  ifdef TERMINFO
  578.     {KS_CDL,        "\033[%p1%dM"},
  579. #  else
  580.     {KS_CDL,        "\033[%dM"},
  581. #  endif
  582. #  ifdef TERMINFO
  583.     {KS_CS,            "\033[%i%p1%d;%p2%dr"},
  584. #  else
  585.     {KS_CS,            "\033[%i%d;%dr"},
  586. #  endif
  587.     {KS_CL,            "\033[H\033[2J"},
  588.     {KS_CD,            "\033[J"},
  589.     {KS_ME,            "\033[m"},
  590.     {KS_MR,            "\033[7m"},
  591.     {KS_MD,            "\033[1m"},
  592.     {KS_UE,            "\033[m"},
  593.     {KS_US,            "\033[4m"},
  594.     {KS_MS,            "\001"},
  595. #  ifdef TERMINFO
  596.     {KS_CM,            "\033[%i%p1%d;%p2%dH"},
  597. #  else
  598.     {KS_CM,            "\033[%i%d;%dH"},
  599. #  endif
  600.     {KS_SR,            "\033M"},
  601. #  ifdef TERMINFO
  602.     {KS_CRI,        "\033[%p1%dC"},
  603. #  else
  604.     {KS_CRI,        "\033[%dC"},
  605. #  endif
  606.     {KS_KS,            "\033[?1h\033="},
  607.     {KS_KE,            "\033[?1l\033>"},
  608. #  ifdef SAVE_XTERM_SCREEN
  609.     {KS_TI,            "\0337\033[?47h"},
  610.     {KS_TE,            "\033[2J\033[?47l\0338"},
  611. #  endif
  612.     {K_UP,            "\033OA"},
  613.     {K_DOWN,        "\033OB"},
  614.     {K_LEFT,        "\033OD"},
  615.     {K_RIGHT,        "\033OC"},
  616.     {K_S_UP,        "\033Ox"},
  617.     {K_S_DOWN,        "\033Or"},
  618.     {K_S_LEFT,        "\033Ot"},
  619.     {K_S_RIGHT,        "\033Ov"},
  620.     {K_F1,            "\033[11~"},
  621.     {K_F2,            "\033[12~"},
  622.     {K_F3,            "\033[13~"},
  623.     {K_F4,            "\033[14~"},
  624.     {K_F5,            "\033[15~"},
  625.     {K_F6,            "\033[17~"},
  626.     {K_F7,            "\033[18~"},
  627.     {K_F8,            "\033[19~"},
  628.     {K_F9,            "\033[20~"},
  629.     {K_F10,            "\033[21~"},
  630.     {K_F11,            "\033[23~"},
  631.     {K_F12,            "\033[24~"},
  632.     {K_HELP,        "\033[28~"},
  633.     {K_UNDO,        "\033[26~"},
  634.     {K_INS,            "\033[2~"},
  635.     {K_HOME,        "\033[7~"},        /* also seen: "\033[1~" */
  636.     {K_END,            "\033[8~"},        /* also seen: "\033[4~" */
  637.     {K_PAGEUP,        "\033[5~"},
  638.     {K_PAGEDOWN,    "\033[6~"},
  639.     /* {K_DEL,            "\033[3~"}, not used */
  640.  
  641.     {BT_EXTRA_KEYS,    ""},
  642.     {TERMCAP2KEY('k', '0'),    "\033[10~"},    /* F0 */
  643.     {TERMCAP2KEY('F', '3'),    "\033[25~"},    /* F13 */
  644.     {TERMCAP2KEY('F', '6'),    "\033[29~"},    /* F16 */
  645.     {TERMCAP2KEY('F', '7'),    "\033[31~"},    /* F17 */
  646.     {TERMCAP2KEY('F', '8'),    "\033[32~"},    /* F18 */
  647.     {TERMCAP2KEY('F', '9'),    "\033[33~"},    /* F19 */
  648.     {TERMCAP2KEY('F', 'A'),    "\033[34~"},    /* F20 */
  649. # endif
  650.  
  651. # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS)
  652. /*
  653.  * iris-ansi for Silicon Graphics machines.
  654.  */
  655.     {KS_NAME,        "iris-ansi"},
  656.     {KS_CE,            "\033[K"},
  657.     {KS_CD,            "\033[J"},
  658.     {KS_AL,            "\033[L"},
  659. #  ifdef TERMINFO
  660.     {KS_CAL,        "\033[%p1%dL"},
  661. #  else
  662.     {KS_CAL,        "\033[%dL"},
  663. #  endif
  664.     {KS_DL,            "\033[M"},
  665. #  ifdef TERMINFO
  666.     {KS_CDL,        "\033[%p1%dM"},
  667. #  else
  668.     {KS_CDL,        "\033[%dM"},
  669. #  endif
  670. /*
  671.  * This "cs" is not working correctly. What is the right one?
  672.  */
  673. #if 0
  674. #  ifdef TERMINFO
  675.     {KS_CS,            "\033[%i%p1%d;%p2%dr"},
  676. #  else
  677.      {KS_CS,        "\033[%i%d;%dr"},
  678. #  endif
  679. #endif
  680.     {KS_CL,            "\033[H\033[2J"},
  681.     {KS_VE,            "\033[9/y\033[12/y\033[=6l"},
  682.     {KS_VS,            "\033[10/y\033[=1h\033[=2l\033[=6h"},
  683.     {KS_SE,            "\033[m"},
  684.     {KS_SO,            "\033[1;7m"},
  685.     {KS_ME,            "\033[m"},
  686.     {KS_MR,            "\033[7m"},
  687.     {KS_MD,            "\033[1m"},
  688.     {KS_UE,            "\033[m"},
  689.     {KS_US,            "\033[4m"},
  690.     {KS_MS,            "\001"}, /* does this really work? */
  691. #  ifdef TERMINFO
  692.     {KS_CM,            "\033[%i%p1%d;%p2%dH"},
  693. #  else
  694.     {KS_CM,            "\033[%i%d;%dH"},
  695. #  endif
  696.     {KS_SR,            "\033M"},
  697. #  ifdef TERMINFO
  698.     {KS_CRI,        "\033[%p1%dC"},
  699. #  else
  700.     {KS_CRI,        "\033[%dC"},
  701. #  endif
  702.     {K_UP,            "\033[A"},
  703.     {K_DOWN,        "\033[B"},
  704.     {K_LEFT,        "\033[D"},
  705.     {K_RIGHT,        "\033[C"},
  706.     {K_S_UP,        "\033[161q"},
  707.     {K_S_DOWN,        "\033[164q"},
  708.     {K_S_LEFT,        "\033[158q"},
  709.     {K_S_RIGHT,        "\033[167q"},
  710.     {K_F1,            "\033[001q"},
  711.     {K_F2,            "\033[002q"},
  712.     {K_F3,            "\033[003q"},
  713.     {K_F4,            "\033[004q"},
  714.     {K_F5,            "\033[005q"},
  715.     {K_F6,            "\033[006q"},
  716.     {K_F7,            "\033[007q"},
  717.     {K_F8,            "\033[008q"},
  718.     {K_F9,            "\033[009q"},
  719.     {K_F10,            "\033[010q"},
  720.     {K_F11,            "\033[011q"},
  721.     {K_F12,            "\033[012q"},
  722.     {K_S_F1,        "\033[013q"},
  723.     {K_S_F2,        "\033[014q"},
  724.     {K_S_F3,        "\033[015q"},
  725.     {K_S_F4,        "\033[016q"},
  726.     {K_S_F5,        "\033[017q"},
  727.     {K_S_F6,        "\033[018q"},
  728.     {K_S_F7,        "\033[019q"},
  729.     {K_S_F8,        "\033[020q"},
  730.     {K_S_F9,        "\033[021q"},
  731.     {K_S_F10,        "\033[022q"},
  732.     {K_S_F11,        "\033[023q"},
  733.     {K_S_F12,        "\033[024q"},
  734.     {K_INS,            "\033[139q"},
  735.     {K_HOME,        "\033[H"},
  736.     {K_END,            "\033[146q"},
  737.     {K_PAGEUP,        "\033[150q"},
  738.     {K_PAGEDOWN,    "\033[154q"},
  739. # endif
  740.  
  741. # if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS)
  742. /*
  743.  * for debugging
  744.  */
  745.     {KS_NAME,        "debug"},
  746.     {KS_CE,            "[CE]"},
  747.     {KS_CD,            "[CD]"},
  748.     {KS_AL,            "[AL]"},
  749. #  ifdef TERMINFO
  750.     {KS_CAL,        "[CAL%p1%d]"},
  751. #  else
  752.     {KS_CAL,        "[CAL%d]"},
  753. #  endif
  754.     {KS_DL,            "[DL]"},
  755. #  ifdef TERMINFO
  756.     {KS_CDL,        "[CDL%p1%d]"},
  757. #  else
  758.     {KS_CDL,        "[CDL%d]"},
  759. #  endif
  760. #  ifdef TERMINFO
  761.     {KS_CS,            "[%dCS%p1%d]"},
  762. #  else
  763.     {KS_CS,            "[%dCS%d]"},
  764. #  endif
  765.     {KS_CL,            "[CL]"},
  766.     {KS_VI,            "[VI]"},
  767.     {KS_VE,            "[VE]"},
  768.     {KS_VS,            "[VS]"},
  769.     {KS_ME,            "[ME]"},
  770.     {KS_MR,            "[MR]"},
  771.     {KS_MD,            "[MD]"},
  772.     {KS_SE,            "[SE]"},
  773.     {KS_SO,            "[SO]"},
  774.     {KS_UE,            "[UE]"},
  775.     {KS_US,            "[US]"},
  776.     {KS_MS,            "[MS]"},
  777. #  ifdef TERMINFO
  778.     {KS_CM,            "[%p1%dCM%p2%d]"},
  779. #  else
  780.     {KS_CM,            "[%dCM%d]"},
  781. #  endif
  782.     {KS_SR,            "[SR]"},
  783. #  ifdef TERMINFO
  784.     {KS_CRI,        "[CRI%p1%d]"},
  785. #  else
  786.     {KS_CRI,        "[CRI%d]"},
  787. #  endif
  788.     {KS_VB,            "[VB]"},
  789.     {KS_KS,            "[KS]"},
  790.     {KS_KE,            "[KE]"},
  791.     {KS_TI,            "[TI]"},
  792.     {KS_TE,            "[TE]"},
  793.     {K_UP,            "[KU]"},
  794.     {K_DOWN,        "[KD]"},
  795.     {K_LEFT,        "[KL]"},
  796.     {K_RIGHT,        "[KR]"},
  797.     {K_S_UP,        "[S-KU]"},
  798.     {K_S_DOWN,        "[S-KD]"},
  799.     {K_S_LEFT,        "[S-KL]"},
  800.     {K_S_RIGHT,        "[S-KR]"},
  801.     {K_F1,            "[F1]"},
  802.     {K_F2,            "[F2]"},
  803.     {K_F3,            "[F3]"},
  804.     {K_F4,            "[F4]"},
  805.     {K_F5,            "[F5]"},
  806.     {K_F6,            "[F6]"},
  807.     {K_F7,            "[F7]"},
  808.     {K_F8,            "[F8]"},
  809.     {K_F9,            "[F9]"},
  810.     {K_F10,            "[F10]"},
  811.     {K_F11,            "[F11]"},
  812.     {K_F12,            "[F12]"},
  813.     {K_S_F1,        "[S-F1]"},
  814.     {K_S_F2,        "[S-F2]"},
  815.     {K_S_F3,        "[S-F3]"},
  816.     {K_S_F4,        "[S-F4]"},
  817.     {K_S_F5,        "[S-F5]"},
  818.     {K_S_F6,        "[S-F6]"},
  819.     {K_S_F7,        "[S-F7]"},
  820.     {K_S_F8,        "[S-F8]"},
  821.     {K_S_F9,        "[S-F9]"},
  822.     {K_S_F10,        "[S-F10]"},
  823.     {K_S_F11,        "[S-F11]"},
  824.     {K_S_F12,        "[S-F12]"},
  825.     {K_HELP,        "[HELP]"},
  826.     {K_UNDO,        "[UNDO]"},
  827.     {K_BS,            "[BS]"},
  828.     {K_INS,            "[INS]"},
  829.     {K_DEL,            "[DEL]"},
  830.     {K_HOME,        "[HOME]"},
  831.     {K_END,            "[END]"},
  832.     {K_PAGEUP,        "[PAGEUP]"},
  833.     {K_PAGEDOWN,    "[PAGEDOWN]"},
  834.     {K_MOUSE,        "[MOUSE]"},
  835. # endif
  836.  
  837. #endif /* NO_BUILTIN_TCAPS */
  838.  
  839. /*
  840.  * The most minimal terminal: only clear screen and cursor positioning
  841.  * Always included.
  842.  */
  843.     {KS_NAME,        "dumb"},
  844.     {KS_CL,            "\014"},
  845. #ifdef TERMINFO
  846.     {KS_CM,            "\033[%i%p1%d;%p2%dH"},
  847. #else
  848.     {KS_CM,            "\033[%i%d;%dH"},
  849. #endif
  850.  
  851. /*
  852.  * end marker
  853.  */
  854.     {KS_NAME,        NULL}
  855.  
  856. };        /* end of builtin_termcaps */
  857.  
  858. /*
  859.  * DEFAULT_TERM is used, when no terminal is specified with -T option or $TERM.
  860.  */
  861. #ifdef AMIGA
  862. # define DEFAULT_TERM    (char_u *)"amiga"
  863. #endif /* AMIGA */
  864.  
  865. #ifdef WIN32
  866. # define DEFAULT_TERM    (char_u *)"win32"
  867. #endif /* WIN32 */
  868.   
  869. #ifdef MSDOS
  870. # define DEFAULT_TERM    (char_u *)"pcterm"
  871. #endif /* MSDOS */
  872.  
  873. #if defined(UNIX) && !defined(MINT)
  874. # define DEFAULT_TERM    (char_u *)"ansi"
  875. #endif /* UNIX */
  876.  
  877. #ifdef MINT
  878. # define DEFAULT_TERM    (char_u *)"vt52"
  879. #endif /* MINT */
  880.  
  881. #ifdef __EMX__
  882. # define DEFAULT_TERM    (char_u *)"os2ansi"
  883. #endif /* __EMX__ */
  884.  
  885. #ifdef VMS
  886. # define DEFAULT_TERM    (char_u *)"ansi"
  887. #endif /* VMS */
  888.  
  889. /*
  890.  * Term_strings contains currently used terminal output strings.
  891.  * It is initialized with the default values by parse_builtin_tcap().
  892.  * The values can be changed by setting the option with the same name.
  893.  */
  894. char_u *(term_strings[KS_LAST + 1]);
  895.  
  896. static int        need_gather = FALSE;            /* need to fill termleader[] */
  897. static char_u    termleader[256 + 1];            /* for check_termcode() */
  898.  
  899.     static struct builtin_term *
  900. find_builtin_term(term)
  901.     char_u        *term;
  902. {
  903.     struct builtin_term *p;
  904.  
  905.     p = builtin_termcaps;
  906.     while (p->bt_string != NULL)
  907.     {
  908.         if (p->bt_entry == KS_NAME)
  909.         {
  910. #ifdef UNIX
  911.             if (STRCMP(p->bt_string, "iris-ansi") == 0 && is_iris_ansi(term))
  912.                 return p;
  913.             else if (STRCMP(p->bt_string, "xterm") == 0 && is_xterm(term))
  914.                 return p;
  915.             else
  916. #endif
  917.                 if (STRCMP(term, p->bt_string) == 0)
  918.                     return p;
  919.         }
  920.         ++p;
  921.     }
  922.     return p;
  923. }
  924.  
  925. /*
  926.  * Parsing of the builtin termcap entries.
  927.  * Caller should check if 'name' is a valid builtin term.
  928.  * The terminal's name is not set, as this is already done in termcapinit().
  929.  */
  930.     static void
  931. parse_builtin_tcap(term)
  932.     char_u    *term;
  933. {
  934.     struct builtin_term        *p;
  935.     char_u                    name[2];
  936.  
  937.     p = find_builtin_term(term);
  938.     for (++p; p->bt_entry != KS_NAME && p->bt_entry != BT_EXTRA_KEYS; ++p)
  939.     {
  940.         if (p->bt_entry < 0x100)    /* KS_xx entry */
  941.         {
  942.             if (term_strings[p->bt_entry] == NULL ||
  943.                                     term_strings[p->bt_entry] == empty_option)
  944.                 term_strings[p->bt_entry] = (char_u *)p->bt_string;
  945.         }
  946.         else
  947.         {
  948.             name[0] = KEY2TERMCAP0(p->bt_entry);
  949.             name[1] = KEY2TERMCAP1(p->bt_entry);
  950.             if (find_termcode(name) == NULL)
  951.                 add_termcode(name, (char_u *)p->bt_string);
  952.         }
  953.     }
  954. }
  955.  
  956. /*
  957.  * Set terminal options for terminal "term".
  958.  * Return OK if terminal 'term' was found in a termcap, FAIL otherwise.
  959.  *
  960.  * While doing this, until ttest(), some options may be NULL, be careful.
  961.  */
  962.     int
  963. set_termname(term)
  964.     char_u *term;
  965. {
  966.     struct builtin_term *termp;
  967. #ifdef HAVE_TGETENT
  968.     int            builtin_first = p_tbi;
  969.     int            try;
  970.     int            termcap_cleared = FALSE;
  971. #endif
  972.     int            width = 0, height = 0;
  973.     char_u        *error_msg = NULL;
  974.     char_u        *bs_p, *del_p;
  975.  
  976.     if (is_builtin_term(term))
  977.     {
  978.         term += 8;
  979. #ifdef HAVE_TGETENT
  980.         builtin_first = 1;
  981. #endif
  982.     }
  983.  
  984. /*
  985.  * If HAVE_TGETENT is not defined, only the builtin termcap is used, otherwise:
  986.  *   If builtin_first is TRUE:
  987.  *     0. try builtin termcap
  988.  *     1. try external termcap
  989.  *     2. if both fail default to a builtin terminal
  990.  *   If builtin_first is FALSE:
  991.  *     1. try external termcap
  992.  *     2. try builtin termcap, if both fail default to a builtin terminal
  993.  */
  994. #ifdef HAVE_TGETENT
  995.     for (try = builtin_first ? 0 : 1; try < 3; ++try)
  996.     {
  997.         /*
  998.          * Use external termcap
  999.          */
  1000.         if (try == 1)
  1001.         {
  1002.             char_u            *p;
  1003.             static char_u    tstrbuf[TBUFSZ];
  1004.             int                i;
  1005.             char_u            tbuf[TBUFSZ];
  1006.             char_u            *tp = tstrbuf;
  1007.             static char     *(key_names[]) =
  1008.                             {
  1009.                             "ku", "kd", "kr",    /* "kl" is a special case */
  1010. # ifdef ARCHIE
  1011.                             "su", "sd",            /* Termcap code made up! */
  1012. # endif
  1013.                             "#4", "%i",
  1014.                             "k1", "k2", "k3", "k4", "k5", "k6",
  1015.                             "k7", "k8", "k9", "k;", "F1", "F2",
  1016.                             "%1", "&8", "kb", "kI", "kD", "kh", 
  1017.                             "@7", "kP", "kN",
  1018.                             NULL
  1019.                             };
  1020.             static struct {
  1021.                             int dest;        /* index in term_strings[] */
  1022.                             char *name;        /* termcap name for string */
  1023.                           } string_names[] =
  1024.                             {    {KS_CE, "ce"}, {KS_AL, "al"}, {KS_CAL, "AL"},
  1025.                                 {KS_DL, "dl"}, {KS_CDL, "DL"}, {KS_CS, "cs"},
  1026.                                 {KS_CL, "cl"}, {KS_CD, "cd"},
  1027.                                 {KS_VI, "vi"}, {KS_VE, "ve"},
  1028.                                 {KS_VS, "vs"}, {KS_ME, "me"}, {KS_MR, "mr"},
  1029.                                 {KS_MD, "md"}, {KS_SE, "se"}, {KS_SO, "so"},
  1030.                                 {KS_CZH, "ZH"}, {KS_CZR, "ZR"}, {KS_UE, "ue"},
  1031.                                 {KS_US, "us"}, {KS_CM, "cm"}, {KS_SR, "sr"},
  1032.                                 {KS_CRI, "RI"}, {KS_VB, "vb"}, {KS_KS, "ks"},
  1033.                                 {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"},
  1034.                                 {0, NULL}
  1035.                             };
  1036.  
  1037.             /*
  1038.              * If the external termcap does not have a matching entry, try the
  1039.              * builtin ones.
  1040.              */
  1041.             if ((error_msg = tgetent_error(tbuf, term)) == NULL)
  1042.             {
  1043.                 if (!termcap_cleared)
  1044.                 {
  1045.                     clear_termoptions();        /* clear old options */
  1046.                     termcap_cleared = TRUE;
  1047.                 }
  1048.  
  1049.             /* get output strings */
  1050.                 for (i = 0; string_names[i].name != NULL; ++i)
  1051.                 {
  1052.                     if (term_strings[string_names[i].dest] == NULL ||
  1053.                                term_strings[string_names[i].dest] == empty_option)
  1054.                         term_strings[string_names[i].dest] =
  1055.                                                TGETSTR(string_names[i].name, &tp);
  1056.                 }
  1057.  
  1058.                 if ((T_MS == NULL || T_MS == empty_option) && tgetflag("ms"))
  1059.                     T_MS = (char_u *)"yes";
  1060.                 if ((T_DB == NULL || T_DB == empty_option) && tgetflag("db"))
  1061.                     T_DB = (char_u *)"yes";
  1062.                 if ((T_DA == NULL || T_DA == empty_option) && tgetflag("da"))
  1063.                     T_DA = (char_u *)"yes";
  1064.  
  1065.  
  1066.             /* get key codes */
  1067.  
  1068.                 for (i = 0; key_names[i] != NULL; ++i)
  1069.                 {
  1070.                     if (find_termcode((char_u *)key_names[i]) == NULL)
  1071.                         add_termcode((char_u *)key_names[i],
  1072.                                                       TGETSTR(key_names[i], &tp));
  1073.                 }
  1074.  
  1075.                     /* if cursor-left == backspace, ignore it (televideo 925) */
  1076.                 if (find_termcode((char_u *)"kl") == NULL)
  1077.                 {
  1078.                     p = TGETSTR("kl", &tp);
  1079.                     if (p != NULL && *p != Ctrl('H'))
  1080.                         add_termcode((char_u *)"kl", p);
  1081.                 }
  1082.  
  1083.                 if (height == 0)
  1084.                     height = tgetnum("li");
  1085.                 if (width == 0)
  1086.                     width = tgetnum("co");
  1087.  
  1088. # ifndef hpux
  1089.                 BC = (char *)TGETSTR("bc", &tp);
  1090.                 UP = (char *)TGETSTR("up", &tp);
  1091.                 p = TGETSTR("pc", &tp);
  1092.                 if (p)
  1093.                     PC = *p;
  1094. # endif /* hpux */
  1095.             }
  1096.         }
  1097.         else        /* try == 0 || try == 2 */
  1098. #endif /* HAVE_TGETENT */
  1099.         /*
  1100.          * Use builtin termcap
  1101.          */
  1102.         {
  1103. #ifdef HAVE_TGETENT
  1104.             /*
  1105.              * If builtin termcap was already used, there is no need to search
  1106.              * for the builtin termcap again, quit now.
  1107.              */
  1108.             if (try == 2 && builtin_first && termcap_cleared)
  1109.                 break;
  1110. #endif
  1111.             /*
  1112.              * search for 'term' in builtin_termcaps[]
  1113.              */
  1114.             termp = find_builtin_term(term);
  1115.             if (termp->bt_string == NULL)        /* did not find it */
  1116.             {
  1117. #ifdef HAVE_TGETENT
  1118.                 /*
  1119.                  * If try == 0, first try the external termcap. If that is not
  1120.                  * found we'll get back here with try == 2.
  1121.                  * If termcap_cleared is set we used the external termcap,
  1122.                  * don't complain about not finding the term in the builtin
  1123.                  * termcap.
  1124.                  */
  1125.                 if (try == 0)                    /* try external one */
  1126.                     continue;
  1127.                 if (termcap_cleared)            /* found in external termcap */
  1128.                     break;
  1129. #endif
  1130.  
  1131.                 fprintf(stderr, "\r\n");
  1132.                 if (error_msg != NULL)
  1133.                 {
  1134.                     fprintf(stderr, (char *)error_msg);
  1135.                     fprintf(stderr, "\r\n");
  1136.                 }
  1137.                 fprintf(stderr, "'%s' not known. Available builtin terminals are:\r\n", term);
  1138.                 for (termp = &(builtin_termcaps[0]); termp->bt_string != NULL;
  1139.                                                                       ++termp)
  1140.                 {
  1141.                     if (termp->bt_entry == KS_NAME)
  1142. #ifdef HAVE_TGETENT
  1143.                         fprintf(stderr, "    builtin_%s\r\n", termp->bt_string);
  1144. #else
  1145.                         fprintf(stderr, "    %s\r\n", termp->bt_string);
  1146. #endif
  1147.                 }
  1148.                 if (!starting)    /* when user typed :set term=xxx, quit here */
  1149.                 {
  1150.                     screen_start();        /* don't know where cursor is now */
  1151.                     wait_return(TRUE);
  1152.                     return FAIL;
  1153.                 }
  1154.                 term = DEFAULT_TERM;
  1155.                 fprintf(stderr, "defaulting to '%s'\r\n", term);
  1156.                 screen_start();            /* don't know where cursor is now */
  1157.                 mch_delay(2000L, TRUE);
  1158.                 set_string_option((char_u *)"term", -1, term, TRUE);
  1159.             }
  1160.             flushbuf();
  1161. #ifdef HAVE_TGETENT
  1162.             if (!termcap_cleared)
  1163.             {
  1164. #endif
  1165.                 clear_termoptions();        /* clear old options */
  1166. #ifdef HAVE_TGETENT
  1167.                 termcap_cleared = TRUE;
  1168.             }
  1169. #endif
  1170.             parse_builtin_tcap(term);
  1171. #ifdef USE_GUI
  1172.             if (STRCMP(term, "gui") == 0)
  1173.             {
  1174.                 flushbuf();
  1175.                 settmode(0);
  1176.                 gui_init();
  1177.                 if (!gui.in_use)        /* failed to start GUI */
  1178.                     settmode(1);
  1179.             }
  1180. #endif /* USE_GUI */
  1181.         }
  1182. #ifdef HAVE_TGETENT
  1183.     }
  1184. #endif
  1185.  
  1186. /*
  1187.  * special: There is no info in the termcap about whether the cursor
  1188.  * positioning is relative to the start of the screen or to the start of the
  1189.  * scrolling region.  We just guess here. Only msdos pcterm is known to do it
  1190.  * relative.
  1191.  */
  1192.     if (STRCMP(term, "pcterm") == 0)
  1193.         T_CSC = (char_u *)"yes";
  1194.     else
  1195.         T_CSC = empty_option;
  1196.  
  1197. #ifdef UNIX
  1198. /*
  1199.  * Any "stty" settings override the default for t_kb from the termcap.
  1200.  * This is in unix.c, because it depends a lot on the version of unix that is
  1201.  * being used.
  1202.  * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly.
  1203.  */
  1204. #ifdef USE_GUI
  1205.     if (!gui.in_use)
  1206. #endif
  1207.         get_stty();
  1208. #endif
  1209.  
  1210. /*
  1211.  * If the termcap has no entry for 'bs' and/or 'del' and the ioctl() also
  1212.  * didn't work, use the default CTRL-H
  1213.  * The default for t_kD is DEL, unless t_kb is DEL.
  1214.  * The strsave'd strings are probably lost forever, well it's only two bytes.
  1215.  * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly.
  1216.  */
  1217. #ifdef USE_GUI
  1218.     if (!gui.in_use)
  1219. #endif
  1220.     {
  1221.         bs_p = find_termcode((char_u *)"kb");
  1222.         del_p = find_termcode((char_u *)"kD");
  1223.         if (bs_p == NULL || *bs_p == NUL)
  1224.             add_termcode((char_u *)"kb", (bs_p = (char_u *)"\010"));
  1225.         if ((del_p == NULL || *del_p == NUL) &&
  1226.                                             (bs_p == NULL || *bs_p != '\177'))
  1227.             add_termcode((char_u *)"kD", (char_u *)"\177");
  1228.     }
  1229.  
  1230. #ifdef USE_MOUSE
  1231.     /*
  1232.      * recognize mouse events in the input stream for xterm, msdos and win32
  1233.      */
  1234.     {    
  1235.         char_u    name[2];
  1236.  
  1237.         name[0] = KS_MOUSE;
  1238.         name[1] = K_FILLER;
  1239. # ifdef UNIX
  1240.         if (is_xterm(term))
  1241.             add_termcode(name, (char_u *)"\033[M");
  1242. # else
  1243.         add_termcode(name, (char_u *)"\233M");
  1244. # endif
  1245.     }
  1246. #endif
  1247.  
  1248. #if defined(AMIGA) || defined(MSDOS) || defined(WIN32) || defined(OS2)
  1249.         /* DEFAULT_TERM indicates that it is the machine console. */
  1250.     if (STRCMP(term, DEFAULT_TERM))
  1251.         term_console = FALSE;
  1252.     else
  1253.     {
  1254.         term_console = TRUE;
  1255. # ifdef AMIGA
  1256.         win_resize_on();        /* enable window resizing reports */
  1257. # endif
  1258.     }
  1259. #endif
  1260.  
  1261. #ifdef UNIX
  1262. /*
  1263.  * 'ttyfast' is default on for xterm, iris-ansi and a few others.
  1264.  */
  1265.     if (is_fastterm(term))
  1266.         p_tf = TRUE;
  1267. #endif
  1268. #if defined(AMIGA) || defined(MSDOS) || defined(WIN32) || defined(OS2)
  1269. /*
  1270.  * 'ttyfast' is default on Amiga, MSDOS, Win32, and OS/2 consoles
  1271.  */
  1272.     if (term_console)
  1273.         p_tf = TRUE;
  1274. #endif
  1275.  
  1276.     ttest(TRUE);        /* make sure we have a valid set of terminal codes */
  1277.     set_term_defaults();    /* use current values as defaults */
  1278.  
  1279.     /*
  1280.      * Initialize the terminal with the appropriate termcap codes.
  1281.      * Set the mouse and window title if possible.
  1282.      * Don't do this when starting, need to parse the .vimrc first, because it
  1283.      * may redefine t_TI etc.
  1284.      */
  1285.     if (!starting)
  1286.     {
  1287.         starttermcap();            /* may change terminal mode */
  1288. #ifdef USE_MOUSE
  1289.         setmouse();                /* may start using the mouse */
  1290. #endif
  1291.         maketitle();            /* may display window title */
  1292.     }
  1293.  
  1294.         /* display initial screen after ttest() checking. jw. */
  1295.     if (width <= 0 || height <= 0)
  1296.     {
  1297.         /* termcap failed to report size */
  1298.         /* set defaults, in case mch_get_winsize also fails */
  1299.         width = 80;
  1300. #if defined MSDOS  ||  defined WIN32
  1301.         height = 25;        /* console is often 25 lines */
  1302. #else
  1303.         height = 24;        /* most terminals are 24 lines */
  1304. #endif
  1305.     }
  1306.     set_winsize(width, height, FALSE);    /* may change Rows */
  1307.     if (!starting)
  1308.     {
  1309.         if (scroll_region)
  1310.             scroll_region_reset();            /* In case Rows changed */
  1311.         check_map_keycodes();    /* check mappings for terminal codes used */
  1312.     }
  1313.  
  1314.     return OK;
  1315. }
  1316.  
  1317. #ifdef HAVE_TGETENT
  1318. /*
  1319.  * Call tgetent()
  1320.  * Return error message if it fails, NULL if it's OK.
  1321.  */
  1322.     static char_u *
  1323. tgetent_error(tbuf, term)
  1324.     char_u    *tbuf;
  1325.     char_u    *term;
  1326. {
  1327.     int        i;
  1328.  
  1329.     i = TGETENT(tbuf, term);
  1330.     if (i == -1)
  1331.         return (char_u *)"Cannot open termcap file";
  1332.     if (i == 0)
  1333. #ifdef TERMINFO
  1334.         return (char_u *)"Terminal entry not found in terminfo";
  1335. #else
  1336.         return (char_u *)"Terminal entry not found in termcap";
  1337. #endif
  1338.     return NULL;
  1339. }
  1340. #endif /* HAVE_TGETENT */
  1341.  
  1342. #if defined(HAVE_TGETENT) && (defined(UNIX) || defined(__EMX__))
  1343. /*
  1344.  * Get Columns and Rows from the termcap. Used after a window signal if the
  1345.  * ioctl() fails. It doesn't make sense to call tgetent each time if the "co"
  1346.  * and "li" entries never change. But on some systems this works.
  1347.  * Errors while getting the entries are ignored.
  1348.  */
  1349.     void
  1350. getlinecol()
  1351. {
  1352.     char_u            tbuf[TBUFSZ];
  1353.  
  1354.     if (term_strings[KS_NAME] != NULL && TGETENT(tbuf, term_strings[KS_NAME]) > 0)
  1355.     {
  1356.         if (Columns == 0)
  1357.             Columns = tgetnum("co");
  1358.         if (Rows == 0)
  1359.             Rows = tgetnum("li");
  1360.     }
  1361. }
  1362. #endif /* defined(HAVE_TGETENT) && defined(UNIX) */
  1363.  
  1364. /*
  1365.  * Get a string entry from the termcap and add it to the list of termcodes.
  1366.  * Used for <t_xx> special keys.
  1367.  * Give an error message for failure when not sourcing.
  1368.  * If force given, replace an existing entry.
  1369.  * Return FAIL if the entry was not found, OK if the entry was added.
  1370.  */
  1371.     int
  1372. add_termcap_entry(name, force)
  1373.     char_u    *name;
  1374.     int        force;
  1375. {
  1376.     char_u    *term;
  1377.     int        key;
  1378.     struct builtin_term *termp;
  1379. #ifdef HAVE_TGETENT
  1380.     char_u    *string;
  1381.     int        i;
  1382.     int        builtin_first;
  1383.     char_u    tbuf[TBUFSZ];
  1384.     char_u    tstrbuf[TBUFSZ];
  1385.     char_u    *tp = tstrbuf;
  1386.     char_u    *error_msg = NULL;
  1387. #endif
  1388.  
  1389. /*
  1390.  * If the GUI is running or will start in a moment, we only support the keys
  1391.  * that the GUI can produce.
  1392.  */
  1393. #ifdef USE_GUI
  1394.     if (gui.in_use || gui.starting)
  1395.         return gui_mch_haskey(name);
  1396. #endif
  1397.  
  1398.     if (!force && find_termcode(name) != NULL)        /* it's already there */
  1399.         return OK;
  1400.  
  1401.     term = term_strings[KS_NAME];
  1402.     if (term == NULL)                        /* just in case */
  1403.         return FAIL;
  1404.  
  1405.     if (is_builtin_term(term))                /* name starts with "builtin_" */
  1406.     {
  1407.         term += 8;
  1408. #ifdef HAVE_TGETENT
  1409.         builtin_first = TRUE;
  1410. #endif
  1411.     }
  1412. #ifdef HAVE_TGETENT
  1413.     else
  1414.         builtin_first = p_tbi;
  1415. #endif
  1416.  
  1417. #ifdef HAVE_TGETENT
  1418. /*
  1419.  * We can get the entry from the builtin termcap and from the external one.
  1420.  * If 'ttybuiltin' is on or the terminal name starts with "builtin_", try
  1421.  * builtin termcap first.
  1422.  * If 'ttybuiltin' is off, try external termcap first.
  1423.  */
  1424.     for (i = 0; i < 2; ++i)
  1425.     {
  1426.         if (!builtin_first == i)
  1427. #endif
  1428.         /*
  1429.          * Search in builtin termcap
  1430.          */
  1431.         {
  1432.             termp = find_builtin_term(term);
  1433.             if (termp->bt_string != NULL)        /* found it */
  1434.             {
  1435.                 key = TERMCAP2KEY(name[0], name[1]);
  1436.                 while (termp->bt_entry != KS_NAME)
  1437.                 {
  1438.                     if (termp->bt_entry == key)
  1439.                     {
  1440.                         add_termcode(name, (char_u *)termp->bt_string);
  1441.                         return OK;
  1442.                     }
  1443.                     ++termp;
  1444.                 }
  1445.             }
  1446.         }
  1447. #ifdef HAVE_TGETENT
  1448.         else
  1449.         /*
  1450.          * Search in external termcap
  1451.          */
  1452.         {
  1453.             error_msg = tgetent_error(tbuf, term);
  1454.             if (error_msg == NULL)
  1455.             {
  1456.                 string = TGETSTR((char *)name, &tp);
  1457.                 if (string != NULL && *string != NUL)
  1458.                 {
  1459.                     add_termcode(name, string);
  1460.                     return OK;
  1461.                 }
  1462.             }
  1463.         }
  1464.     }
  1465. #endif
  1466.  
  1467.     if (sourcing_name == NULL)
  1468.     {
  1469. #ifdef HAVE_TGETENT
  1470.         if (error_msg != NULL)
  1471.             EMSG(error_msg);
  1472.         else
  1473. #endif
  1474.             EMSG2("No \"%s\" entry in termcap", name);
  1475.     }
  1476.     return FAIL;
  1477. }
  1478.  
  1479.     static int
  1480. is_builtin_term(name)
  1481.     char_u    *name;
  1482. {
  1483.     return (STRNCMP(name, "builtin_", (size_t)8) == 0);
  1484. }
  1485.  
  1486. static char_u *tltoa __PARMS((unsigned long));
  1487.  
  1488.     static char_u *
  1489. tltoa(i)
  1490.     unsigned long i;
  1491. {
  1492.     static char_u buf[16];
  1493.     char_u        *p;
  1494.  
  1495.     p = buf + 15;
  1496.     *p = '\0';
  1497.     do
  1498.     {
  1499.         --p;
  1500.         *p = (char_u) (i % 10 + '0');
  1501.         i /= 10;
  1502.     }
  1503.     while (i > 0 && p > buf);
  1504.     return p;
  1505. }
  1506.  
  1507. #ifndef HAVE_TGETENT
  1508.  
  1509. /*
  1510.  * minimal tgoto() implementation.
  1511.  * no padding and we only parse for %i %d and %+char
  1512.  */
  1513. char *tgoto __ARGS((char *, int, int));
  1514.  
  1515.     char *
  1516. tgoto(cm, x, y)
  1517.     char *cm;
  1518.     int x, y;
  1519. {
  1520.     static char buf[30];
  1521.     char *p, *s, *e;
  1522.  
  1523.     if (!cm)
  1524.         return "OOPS";
  1525.     e = buf + 29;
  1526.     for (s = buf; s < e && *cm; cm++)
  1527.     {
  1528.         if (*cm != '%')
  1529.         {
  1530.             *s++ = *cm;
  1531.             continue;
  1532.         }
  1533.         switch (*++cm)
  1534.         {
  1535.         case 'd':
  1536.             p = (char *)tltoa((unsigned long)y);
  1537.             y = x;
  1538.             while (*p)
  1539.                 *s++ = *p++;
  1540.             break;
  1541.         case 'i':
  1542.             x++;
  1543.             y++;
  1544.             break;
  1545.         case '+':
  1546.             *s++ = (char)(*++cm + y);
  1547.             y = x;
  1548.             break;
  1549.         case '%':
  1550.             *s++ = *cm;
  1551.             break;
  1552.         default:
  1553.             return "OOPS";
  1554.         }
  1555.     }
  1556.     *s = '\0';
  1557.     return buf;
  1558. }
  1559.  
  1560. #endif /* HAVE_TGETENT */
  1561.  
  1562. /*
  1563.  * Set the terminal name to "term" and initialize the terminal options.
  1564.  * If "term" is NULL or empty, get the terminal name from the environment.
  1565.  * If that fails, use the default terminal name.
  1566.  */
  1567.     void
  1568. termcapinit(term)
  1569.     char_u *term;
  1570. {
  1571.     if (!term || !*term)
  1572.         term = vim_getenv((char_u *)"TERM");
  1573.     if (!term || !*term)
  1574.         term = DEFAULT_TERM;
  1575.     set_string_option((char_u *)"term", -1, term, TRUE);
  1576.     /*
  1577.      * Avoid using "term" here, because the next vim_getenv() may overwrite it.
  1578.      */
  1579.     set_termname(term_strings[KS_NAME] != NULL ? term_strings[KS_NAME] : term);
  1580. }
  1581.  
  1582. /*
  1583.  * the number of calls to mch_write is reduced by using the buffer "outbuf"
  1584.  */
  1585. #undef BSIZE            /* hpux has BSIZE in sys/option.h */
  1586. #define BSIZE    2048
  1587. static char_u            outbuf[BSIZE];
  1588. static int                bpos = 0;        /* number of chars in outbuf */
  1589.  
  1590. /*
  1591.  * flushbuf(): flush the output buffer
  1592.  */
  1593.     void
  1594. flushbuf()
  1595. {
  1596.     if (bpos != 0)
  1597.     {
  1598.         mch_write(outbuf, bpos);
  1599.         bpos = 0;
  1600.     }
  1601. }
  1602.  
  1603. #ifdef USE_GUI
  1604. /*
  1605.  * trash_output_buf(): Throw away the contents of the output buffer
  1606.  */
  1607.     void
  1608. trash_output_buf()
  1609. {
  1610.     bpos = 0;
  1611. }
  1612. #endif
  1613.  
  1614. /*
  1615.  * outchar(c): put a character into the output buffer.
  1616.  *               Flush it if it becomes full.
  1617.  * This should not be used for outputting text on the screen (use functions like
  1618.  * msg_outstr() and screen_outchar() for that).
  1619.  */
  1620.     void
  1621. outchar(c)
  1622.     unsigned    c;
  1623. {
  1624. #if defined(UNIX) || defined(VMS) || defined(AMIGA)
  1625.     if (c == '\n')        /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
  1626.         outchar('\r');
  1627. #endif
  1628.  
  1629.     outbuf[bpos++] = c;
  1630.  
  1631.     /* For testing we flush each time. */
  1632.     if (bpos >= BSIZE || p_wd)
  1633.         flushbuf();
  1634. }
  1635.  
  1636. static void outchar_nf __ARGS((unsigned));
  1637.  
  1638. /*
  1639.  * outchar_nf(c): like outchar(), but don't flush when p_wd is set
  1640.  */
  1641.     static void
  1642. outchar_nf(c)
  1643.     unsigned    c;
  1644. {
  1645. #if defined(UNIX) || defined(VMS) || defined(AMIGA)
  1646.     if (c == '\n')        /* turn LF into CR-LF (CRMOD doesn't seem to do this) */
  1647.         outchar_nf('\r');
  1648. #endif
  1649.  
  1650.     outbuf[bpos++] = c;
  1651.  
  1652.     /* For testing we flush each time. */
  1653.     if (bpos >= BSIZE)
  1654.         flushbuf();
  1655. }
  1656.  
  1657. /*
  1658.  * a never-padding outstr.
  1659.  * use this whenever you don't want to run the string through tputs.
  1660.  * tputs above is harmless, but tputs from the termcap library
  1661.  * is likely to strip off leading digits, that it mistakes for padding
  1662.  * information. (jw)
  1663.  * This should only be used for writing terminal codes, not for outputting
  1664.  * normal text (use functions like msg_outstr() and screen_outchar() for that).
  1665.  */
  1666.     void
  1667. outstrn(s)
  1668.     char_u *s;
  1669. {
  1670.     if (bpos > BSIZE - 20)        /* avoid terminal strings being split up */
  1671.         flushbuf();
  1672.     while (*s)
  1673.         outchar_nf(*s++);
  1674.  
  1675.     /* For testing we write one string at a time. */
  1676.     if (p_wd)
  1677.         flushbuf();
  1678. }
  1679.  
  1680. /*
  1681.  * outstr(s): put a string character at a time into the output buffer.
  1682.  * If HAVE_TGETENT is defined use the termcap parser. (jw)
  1683.  * This should only be used for writing terminal codes, not for outputting
  1684.  * normal text (use functions like msg_outstr() and screen_outchar() for that).
  1685.  */
  1686.     void
  1687. outstr(s)
  1688.     register char_u             *s;
  1689. {
  1690.     if (bpos > BSIZE - 20)        /* avoid terminal strings being split up */
  1691.         flushbuf();
  1692.     if (s)
  1693. #ifdef HAVE_TGETENT
  1694.         tputs((char *)s, 1, TPUTSFUNCAST outchar_nf);
  1695. #else
  1696.         while (*s)
  1697.             outchar_nf(*s++);
  1698. #endif
  1699.  
  1700.     /* For testing we write one string at a time. */
  1701.     if (p_wd)
  1702.         flushbuf();
  1703. }
  1704.  
  1705. /*
  1706.  * cursor positioning using termcap parser. (jw)
  1707.  */
  1708.     void
  1709. windgoto(row, col)
  1710.     int        row;
  1711.     int        col;
  1712. {
  1713.     if (col != screen_cur_col || row != screen_cur_row)
  1714.     {
  1715.         /*
  1716.          * When positioning on the same row, column 0, use CR, it's just one
  1717.          * character.  Don't do this when the cursor has moved past the end of
  1718.          * the line, the cursor position is undefined then.
  1719.          */
  1720.         if (row == screen_cur_row && col == 0 && screen_cur_col < Columns)
  1721.         {
  1722.             outchar('\r');
  1723.             screen_cur_col = 0;
  1724.         }
  1725.         else
  1726.         {
  1727.             OUTSTR(tgoto((char *)T_CM, col, row));
  1728.             screen_cur_col = col;
  1729.             screen_cur_row = row;
  1730.         }
  1731.     }
  1732. }
  1733.  
  1734. /*
  1735.  * Set cursor to current position.
  1736.  */
  1737.  
  1738.     void
  1739. setcursor()
  1740. {
  1741.     if (!RedrawingDisabled)
  1742.         windgoto(curwin->w_winpos + curwin->w_row,
  1743. #ifdef RIGHTLEFT
  1744.                 curwin->w_p_rl ? (int)Columns - 1 - curwin->w_col :
  1745. #endif
  1746.                                                             curwin->w_col);
  1747. }
  1748.  
  1749. /*
  1750.  * Make sure we have a valid set or terminal options.
  1751.  * Replace all entries that are NULL by empty_option
  1752.  */
  1753.     void
  1754. ttest(pairs)
  1755.     int    pairs;
  1756. {
  1757.     char *t = NULL;
  1758.  
  1759.     check_options();                /* make sure no options are NULL */
  1760.  
  1761.   /* hard requirements */
  1762.     if (*T_CL == NUL)                /* erase display */
  1763.         t = "cl";
  1764.     if (*T_CM == NUL)                /* cursor motion */
  1765.         t = "cm";
  1766.  
  1767.     if (t)
  1768.         EMSG2("terminal capability %s required", t);
  1769.  
  1770. /*
  1771.  * if "cs" defined, use a scroll region, it's faster.
  1772.  */
  1773.     if (*T_CS != NUL)
  1774.         scroll_region = TRUE;
  1775.     else
  1776.         scroll_region = FALSE;
  1777.  
  1778.     if (pairs)
  1779.     {
  1780.       /* optional pairs */
  1781.             /* TP goes to normal mode for TI (invert) and TB (bold) */
  1782.         if (*T_ME == NUL)
  1783.             T_ME = T_MR = T_MD = empty_option;
  1784.         if (*T_SO == NUL || *T_SE == NUL)
  1785.             T_SO = T_SE = empty_option;
  1786.         if (*T_US == NUL || *T_UE == NUL)
  1787.             T_US = T_UE = empty_option;
  1788.         if (*T_CZH == NUL || *T_CZR == NUL)
  1789.             T_CZH = T_CZR = empty_option;
  1790.             /* T_VE is needed even though T_VI is not defined */
  1791.         if (*T_VE == NUL)
  1792.             T_VI = empty_option;
  1793.             /* if 'mr' or 'me' is not defined use 'so' and 'se' */
  1794.         if (*T_ME == NUL)
  1795.         {
  1796.             T_ME = T_SE;
  1797.             T_MR = T_SO;
  1798.             T_MD = T_SO;
  1799.         }
  1800.             /* if 'so' or 'se' is not defined use 'mr' and 'me' */
  1801.         if (*T_SO == NUL)
  1802.         {
  1803.             T_SE = T_ME;
  1804.             if (*T_MR == NUL)
  1805.                 T_SO = T_MD;
  1806.             else
  1807.                 T_SO = T_MR;
  1808.         }
  1809.             /* if 'ZH' or 'ZR' is not defined use 'mr' and 'me' */
  1810.         if (*T_CZH == NUL)
  1811.         {
  1812.             T_CZR = T_ME;
  1813.             if (*T_MR == NUL)
  1814.                 T_CZH = T_MD;
  1815.             else
  1816.                 T_CZH = T_MR;
  1817.         }
  1818.     }
  1819.     need_gather = TRUE;
  1820. }
  1821.  
  1822. /*
  1823.  * Represent the given long_u as individual bytes, with the most significant
  1824.  * byte first, and store them in dst.
  1825.  */
  1826.     void
  1827. add_long_to_buf(val, dst)
  1828.     long_u    val;
  1829.     char_u    *dst;
  1830. {
  1831.     int        i;
  1832.     int        shift;
  1833.  
  1834.     for (i = 1; i <= sizeof(long_u); i++)
  1835.     {
  1836.         shift = 8 * (sizeof(long_u) - i);
  1837.         dst[i - 1] = (char_u) ((val >> shift) & 0xff);
  1838.     }
  1839. }
  1840.  
  1841. /*
  1842.  * Interpret the next string of bytes in buf as a long integer, with the most
  1843.  * significant byte first.    Note that it is assumed that buf has been through
  1844.  * inchar(), so that NUL and K_SPECIAL will be represented as three bytes each.
  1845.  * Puts result in val, and returns the number of bytes read from buf
  1846.  * (between sizeof(long_u) and 2 * sizeof(long_u)), or -1 if not enough bytes
  1847.  * were present.
  1848.  */
  1849.     int
  1850. get_long_from_buf(buf, val)
  1851.     char_u    *buf;
  1852.     long_u    *val;
  1853. {
  1854.     int        len;
  1855.     char_u    bytes[sizeof(long_u)];
  1856.     int        i;
  1857.     int        shift;
  1858.  
  1859.     *val = 0;
  1860.     len = get_bytes_from_buf(buf, bytes, (int)sizeof(long_u));
  1861.     if (len != -1)
  1862.     {
  1863.         for (i = 0; i < sizeof(long_u); i++)
  1864.         {
  1865.             shift = 8 * (sizeof(long_u) - 1 - i);
  1866.             *val += (long_u)bytes[i] << shift;
  1867.         }
  1868.     }
  1869.     return len;
  1870. }
  1871.  
  1872. /*
  1873.  * Read the next num_bytes bytes from buf, and store them in bytes.  Assume
  1874.  * that buf has been through inchar().    Returns the actual number of bytes used
  1875.  * from buf (between num_bytes and num_bytes*2), or -1 if not enough bytes were
  1876.  * available.
  1877.  */
  1878.     static int
  1879. get_bytes_from_buf(buf, bytes, num_bytes)
  1880.     char_u    *buf;
  1881.     char_u    *bytes;
  1882.     int        num_bytes;
  1883. {
  1884.     int        len = 0;
  1885.     int        i;
  1886.     char_u    c;
  1887.  
  1888.     for (i = 0; i < num_bytes; i++)
  1889.     {
  1890.         if ((c = buf[len++]) == NUL)
  1891.             return -1;
  1892.         if (c == K_SPECIAL)
  1893.         {
  1894.             if (buf[len] == NUL || buf[len + 1] == NUL)        /* cannot happen? */
  1895.                 return -1;
  1896.             if (buf[len++] == KS_ZERO)
  1897.                 c = NUL;
  1898.             ++len;        /* skip K_FILLER */
  1899.             /* else it should be KS_SPECIAL, and c already equals K_SPECIAL */
  1900.         }
  1901.         bytes[i] = c;
  1902.     }
  1903.     return len;
  1904. }
  1905.  
  1906. /*
  1907.  * outnum - output a (big) number fast
  1908.  */
  1909.     void
  1910. outnum(n)
  1911.     register long n;
  1912. {
  1913.     OUTSTRN(tltoa((unsigned long)n));
  1914. }
  1915.  
  1916.     void
  1917. check_winsize()
  1918. {
  1919.     static int    old_Rows = 0;
  1920.  
  1921.     if (Columns < MIN_COLUMNS)
  1922.         Columns = MIN_COLUMNS;
  1923.     if (Rows < min_rows())        /* need room for one window and command line */
  1924.         Rows = min_rows();
  1925.  
  1926.     if (old_Rows != Rows)
  1927.     {
  1928.         old_Rows = Rows;
  1929.         screen_new_rows();            /* may need to update window sizes */
  1930.     }
  1931. }
  1932.  
  1933. /*
  1934.  * set window size
  1935.  * If 'mustset' is TRUE, we must set Rows and Columns, do not get real
  1936.  * window size (this is used for the :win command).
  1937.  * If 'mustset' is FALSE, we may try to get the real window size and if
  1938.  * it fails use 'width' and 'height'.
  1939.  */
  1940.     void
  1941. set_winsize(width, height, mustset)
  1942.     int        width, height;
  1943.     int        mustset;
  1944. {
  1945.     register int        tmp;
  1946.  
  1947.     if (width < 0 || height < 0)    /* just checking... */
  1948.         return;
  1949.  
  1950.                                     /* postpone the resizing */
  1951.     if (State == HITRETURN || State == SETWSIZE)
  1952.     {
  1953.         State = SETWSIZE;
  1954.         return;
  1955.     }
  1956.     if (State != ASKMORE && State != EXTERNCMD)
  1957.         screenclear();
  1958.     else
  1959.         screen_start();                    /* don't know where cursor is now */
  1960. #ifdef AMIGA
  1961.     flushbuf();            /* must do this before mch_get_winsize for some
  1962.                             obscure reason */
  1963. #endif /* AMIGA */
  1964.     if (mustset || (mch_get_winsize() == FAIL && height != 0))
  1965.     {
  1966.         Rows = height;
  1967.         Columns = width;
  1968.         check_winsize();        /* always check, to get p_scroll right */
  1969.         mch_set_winsize();
  1970.     }
  1971.     else
  1972.         check_winsize();        /* always check, to get p_scroll right */
  1973.     if (!starting)
  1974.     {
  1975.         comp_Botline_all();
  1976.         if (State == ASKMORE || State == EXTERNCMD)
  1977.         {
  1978.             screenalloc(FALSE);    /* don't redraw, just adjust screen size */
  1979.             if (State == ASKMORE)
  1980.             {
  1981.                 msg_moremsg(FALSE);    /* display --more-- message again */
  1982.                 msg_row = Rows - 1;
  1983.             }
  1984.             else
  1985.                 windgoto(msg_row, msg_col);    /* put cursor back */
  1986.         }
  1987.         else
  1988.         {
  1989.             tmp = RedrawingDisabled;
  1990.             RedrawingDisabled = FALSE;
  1991.             updateScreen(CURSUPD);
  1992.             RedrawingDisabled = tmp;
  1993.             if (State == CMDLINE)
  1994.                 redrawcmdline();
  1995.             else
  1996.                 setcursor();
  1997.         }
  1998.     }
  1999.     flushbuf();
  2000. }
  2001.  
  2002.     void
  2003. settmode(raw)
  2004.     int     raw;
  2005. {
  2006.     static int    oldraw = FALSE;
  2007.  
  2008. #ifdef USE_GUI
  2009.     /* don't set the term where gvim was started in raw mode */
  2010.     if (gui.in_use)
  2011.         return;
  2012. #endif
  2013.     if (full_screen)
  2014.     {
  2015.         /*
  2016.          * When returning after calling a shell we want to really set the
  2017.          * terminal to raw mode, even though we think it already is, because
  2018.          * the shell program may have reset the terminal mode.
  2019.          * When we think the terminal is not-raw, don't try to set it to
  2020.          * not-raw again, because that causes problems (logout!) on some
  2021.          * machines.
  2022.          */
  2023.         if (raw || oldraw)
  2024.         {
  2025.             flushbuf();
  2026.             mch_settmode(raw);    /* machine specific function */
  2027. #ifdef USE_MOUSE
  2028.             if (!raw)
  2029.                 mch_setmouse(FALSE);            /* switch mouse off */
  2030.             else
  2031.                 setmouse();                        /* may switch mouse on */
  2032. #endif
  2033.             flushbuf();
  2034.             oldraw = raw;
  2035.         }
  2036.     }
  2037. }
  2038.  
  2039.     void
  2040. starttermcap()
  2041. {
  2042.     if (full_screen && !termcap_active)
  2043.     {
  2044.         outstr(T_TI);                    /* start termcap mode */
  2045.         outstr(T_KS);                    /* start "keypad transmit" mode */
  2046.         flushbuf();
  2047.         termcap_active = TRUE;
  2048.         screen_start();                    /* don't know where cursor is now */
  2049.     }
  2050. }
  2051.  
  2052.     void
  2053. stoptermcap()
  2054. {
  2055.     if (full_screen && termcap_active)
  2056.     {
  2057.         outstr(T_KE);                    /* stop "keypad transmit" mode */
  2058.         flushbuf();
  2059.         termcap_active = FALSE;
  2060.         cursor_on();                    /* just in case it is still off */
  2061.         outstr(T_TE);                    /* stop termcap mode */
  2062.         screen_start();                    /* don't know where cursor is now */
  2063.     }
  2064. }
  2065.  
  2066. #ifdef USE_MOUSE
  2067. /*
  2068.  * setmouse() - switch mouse on/off depending on current mode and 'mouse'
  2069.  */
  2070.     void
  2071. setmouse()
  2072. {
  2073.     int        checkfor;
  2074.  
  2075. # ifdef USE_GUI
  2076.     if (gui.in_use)
  2077.         return;
  2078. # endif
  2079.     if (*p_mouse == NUL)            /* be quick when mouse is off */
  2080.         return;
  2081.  
  2082.     if (VIsual_active)
  2083.         checkfor = MOUSE_VISUAL;
  2084.     else if (State == HITRETURN)
  2085.         checkfor = MOUSE_RETURN;
  2086.     else if (State & INSERT)
  2087.         checkfor = MOUSE_INSERT;
  2088.     else if (State & CMDLINE)
  2089.         checkfor = MOUSE_COMMAND;
  2090.     else
  2091.         checkfor = MOUSE_NORMAL;                /* assume normal mode */
  2092.     
  2093.     if (mouse_has(checkfor))
  2094.         mch_setmouse(TRUE);
  2095.     else
  2096.         mch_setmouse(FALSE);
  2097. }
  2098.  
  2099. /*
  2100.  * Return TRUE if
  2101.  * - "c" is in 'mouse', or
  2102.  * - 'a' is in 'mouse' and "c" is in MOUSE_A, or
  2103.  * - the current buffer is a help file and 'h' is in 'mouse' and we are in a
  2104.  *   normal editing mode (not at hit-return message).
  2105.  */
  2106.     int
  2107. mouse_has(c)
  2108.     int        c;
  2109. {
  2110.     return (vim_strchr(p_mouse, c) != NULL ||
  2111.                     (vim_strchr(p_mouse, 'a') != NULL &&
  2112.                                   vim_strchr((char_u *)MOUSE_A, c) != NULL) ||
  2113.                     (c != MOUSE_RETURN && curbuf->b_help &&
  2114.                                             vim_strchr(p_mouse, MOUSE_HELP)));
  2115. }
  2116. #endif
  2117.  
  2118. /*
  2119.  * By outputting the 'cursor very visible' termcap code, for some windowed
  2120.  * terminals this makes the screen scrolled to the correct position.
  2121.  * Used when starting Vim or returning from a shell.
  2122.  */
  2123.     void
  2124. scroll_start()
  2125. {
  2126.     if (*T_VS != NUL)
  2127.     {
  2128.         outstr(T_VS);
  2129.         outstr(T_VE);
  2130.         screen_start();                    /* don't know where cursor is now */
  2131.     }
  2132. }
  2133.  
  2134. /*
  2135.  * enable cursor, unless in Visual mode or no inversion possible
  2136.  */
  2137. static int cursor_is_off = FALSE;
  2138.  
  2139.     void
  2140. cursor_on()
  2141. {
  2142.     if (full_screen)
  2143.     {
  2144.         if (cursor_is_off && (!VIsual_active || highlight == NULL))
  2145.         {
  2146.             outstr(T_VE);
  2147.             cursor_is_off = FALSE;
  2148.         }
  2149.     }
  2150. }
  2151.  
  2152.     void
  2153. cursor_off()
  2154. {
  2155.     if (full_screen)
  2156.     {
  2157.         if (!cursor_is_off)
  2158.             outstr(T_VI);            /* disable cursor */
  2159.         cursor_is_off = TRUE;
  2160.     }
  2161. }
  2162.  
  2163. /*
  2164.  * Set scrolling region for window 'wp'.
  2165.  * The region starts 'off' lines from the start of the window.
  2166.  */
  2167.     void
  2168. scroll_region_set(wp, off)
  2169.     WIN        *wp;
  2170.     int        off;
  2171. {
  2172.     OUTSTR(tgoto((char *)T_CS, wp->w_winpos + wp->w_height - 1,
  2173.                                                          wp->w_winpos + off));
  2174.     screen_start();                    /* don't know where cursor is now */
  2175. }
  2176.  
  2177. /*
  2178.  * Reset scrolling region to the whole screen.
  2179.  */
  2180.     void
  2181. scroll_region_reset()
  2182. {
  2183.     OUTSTR(tgoto((char *)T_CS, (int)Rows - 1, 0));
  2184.     screen_start();                    /* don't know where cursor is now */
  2185. }
  2186.  
  2187.  
  2188. /*
  2189.  * List of terminal codes that are currently recognized.
  2190.  */
  2191.  
  2192. struct termcode
  2193. {
  2194.     char_u    name[2];        /* termcap name of entry */
  2195.     char_u    *code;            /* terminal code (in allocated memory) */
  2196.     int        len;            /* STRLEN(code) */
  2197. } *termcodes = NULL;
  2198.  
  2199. static int    tc_max_len = 0;    /* number of entries that termcodes[] can hold */
  2200. static int    tc_len = 0;        /* current number of entries in termcodes[] */
  2201.  
  2202.     void
  2203. clear_termcodes()
  2204. {
  2205.     while (tc_len > 0)
  2206.         vim_free(termcodes[--tc_len].code);
  2207.     vim_free(termcodes);
  2208.     termcodes = NULL;
  2209.     tc_max_len = 0;
  2210.  
  2211. #ifdef HAVE_TGETENT
  2212.     BC = (char *)empty_option;
  2213.     UP = (char *)empty_option;
  2214.     PC = ' ';                    /* set pad character to space */
  2215.     ospeed = 0;
  2216. #endif
  2217.  
  2218.     need_gather = TRUE;            /* need to fill termleader[] */
  2219. }
  2220.  
  2221. /*
  2222.  * Add a new entry to the list of terminal codes.
  2223.  * The list is kept alphabetical for ":set termcap"
  2224.  */
  2225.     void
  2226. add_termcode(name, string)
  2227.     char_u    *name;
  2228.     char_u    *string;
  2229. {
  2230.     struct termcode *new_tc;
  2231.     int                i, j;
  2232.     char_u            *s;
  2233.  
  2234.     if (string == NULL || *string == NUL)
  2235.     {
  2236.         del_termcode(name);
  2237.         return;
  2238.     }
  2239.  
  2240.     s = strsave(string);
  2241.     if (s == NULL)
  2242.         return;
  2243.  
  2244.     need_gather = TRUE;            /* need to fill termleader[] */
  2245.  
  2246.     /*
  2247.      * need to make space for more entries
  2248.      */
  2249.     if (tc_len == tc_max_len)
  2250.     {
  2251.         tc_max_len += 20;
  2252.         new_tc = (struct termcode *)alloc(
  2253.                             (unsigned)(tc_max_len * sizeof(struct termcode)));
  2254.         if (new_tc == NULL)
  2255.         {
  2256.             tc_max_len -= 20;
  2257.             return;
  2258.         }
  2259.         for (i = 0; i < tc_len; ++i)
  2260.             new_tc[i] = termcodes[i];
  2261.         vim_free(termcodes);
  2262.         termcodes = new_tc;
  2263.     }
  2264.  
  2265.     /*
  2266.      * Look for existing entry with the same name, it is replaced.
  2267.      * Look for an existing entry that is alphabetical higher, the new entry
  2268.      * is inserted in front of it.
  2269.      */
  2270.     for (i = 0; i < tc_len; ++i)
  2271.     {
  2272.         if (termcodes[i].name[0] < name[0])
  2273.             continue;
  2274.         if (termcodes[i].name[0] == name[0])
  2275.         {
  2276.             if (termcodes[i].name[1] < name[1])
  2277.                 continue;
  2278.             /*
  2279.              * Exact match: Replace old code.
  2280.              */
  2281.             if (termcodes[i].name[1] == name[1])
  2282.             {
  2283.                 vim_free(termcodes[i].code);
  2284.                 --tc_len;
  2285.                 break;
  2286.             }
  2287.         }
  2288.         /*
  2289.          * Found alphabetical larger entry, move rest to insert new entry
  2290.          */
  2291.         for (j = tc_len; j > i; --j)
  2292.             termcodes[j] = termcodes[j - 1];
  2293.         break;
  2294.     }
  2295.  
  2296.     termcodes[i].name[0] = name[0];
  2297.     termcodes[i].name[1] = name[1];
  2298.     termcodes[i].code = s;
  2299.     termcodes[i].len = STRLEN(s);
  2300.     ++tc_len;
  2301. }
  2302.  
  2303.     char_u    *
  2304. find_termcode(name)
  2305.     char_u    *name;
  2306. {
  2307.     int        i;
  2308.  
  2309.     for (i = 0; i < tc_len; ++i)
  2310.         if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
  2311.             return termcodes[i].code;
  2312.     return NULL;
  2313. }
  2314.  
  2315.     char_u *
  2316. get_termcode(i)
  2317.     int        i;
  2318. {
  2319.     if (i >= tc_len)
  2320.         return NULL;
  2321.     return &termcodes[i].name[0];
  2322. }
  2323.  
  2324.     void
  2325. del_termcode(name)
  2326.     char_u    *name;
  2327. {
  2328.     int        i;
  2329.  
  2330.     if (termcodes == NULL)        /* nothing there yet */
  2331.         return;
  2332.  
  2333.     need_gather = TRUE;            /* need to fill termleader[] */
  2334.  
  2335.     for (i = 0; i < tc_len; ++i)
  2336.         if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1])
  2337.         {
  2338.             vim_free(termcodes[i].code);
  2339.             --tc_len;
  2340.             while (i < tc_len)
  2341.             {
  2342.                 termcodes[i] = termcodes[i + 1];
  2343.                 ++i;
  2344.             }
  2345.             return;
  2346.         }
  2347.     /* not found. Give error message? */
  2348. }
  2349.  
  2350. /*
  2351.  * Check if typebuf[] contains a terminal key code.
  2352.  * Check from typebuf[typeoff] to typebuf[typeoff + max_offset].
  2353.  * Return 0 for no match, -1 for partial match, > 0 for full match.
  2354.  * With a match, the match is removed, the replacement code is inserted in
  2355.  * typebuf[] and the number of characters in typebuf[] is returned.
  2356.  */
  2357.     int
  2358. check_termcode(max_offset)
  2359.     int        max_offset;
  2360. {
  2361.     register char_u        *tp;
  2362.     register char_u        *p;
  2363.     int            slen = 0;        /* init for GCC */
  2364.     int            len;
  2365.     int            offset;
  2366.     char_u        key_name[2];
  2367.     int            new_slen;
  2368.     int            extra;
  2369.     char_u        string[MAX_KEY_CODE_LEN + 1];
  2370.     int            i;
  2371. #ifdef USE_GUI
  2372.     long_u        val;
  2373. #endif
  2374. #ifdef USE_MOUSE
  2375.     char_u        bytes[3];
  2376.     int            num_bytes;
  2377.     int            mouse_code;
  2378.     int            modifiers;
  2379.     int            is_click, is_drag;
  2380.     int            current_button;
  2381.     static int    held_button = MOUSE_RELEASE;
  2382.     static int    orig_num_clicks = 1;
  2383.     static int    orig_mouse_code = 0x0;
  2384. # if defined(UNIX) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
  2385.     static int    orig_mouse_col = 0;
  2386.     static int    orig_mouse_row = 0;
  2387.     static linenr_t    orig_topline = 0;
  2388.     static struct timeval  orig_mouse_time = {0, 0};
  2389.                                         /* time of previous mouse click */
  2390.     struct timeval  mouse_time;            /* time of current mouse click */
  2391.     long        timediff;                /* elapsed time in msec */
  2392. # endif
  2393. #endif
  2394.  
  2395.     /*
  2396.      * Speed up the checks for terminal codes by gathering all first bytes
  2397.      * used in termleader[].  Often this is just a single <Esc>.
  2398.      */
  2399.     if (need_gather)
  2400.         gather_termleader();
  2401.  
  2402.     /*
  2403.      * Check at several positions in typebuf[], to catch something like
  2404.      * "x<Up>" that can be mapped. Stop at max_offset, because characters
  2405.      * after that cannot be used for mapping, and with @r commands typebuf[]
  2406.      * can become very long.
  2407.      * This is used often, KEEP IT FAST!
  2408.      */
  2409.     for (offset = 0; offset < typelen && offset < max_offset; ++offset)
  2410.     {
  2411.         tp = typebuf + typeoff + offset;
  2412.  
  2413.         /*
  2414.          * Don't check characters after K_SPECIAL, those are already
  2415.          * translated terminal chars (avoid translating ~@^Hx).
  2416.          */
  2417.         if (*tp == K_SPECIAL)
  2418.         {
  2419.             offset += 2;        /* there are always 2 extra characters */
  2420.             continue;
  2421.         }
  2422.  
  2423.         /*
  2424.          * Skip this position if the character does not appear as the first
  2425.          * character in term_strings. This speeds up a lot, since most
  2426.          * termcodes start with the same character (ESC or CSI).
  2427.          */
  2428.         i = *tp;
  2429.         for (p = termleader; *p && *p != i; ++p)
  2430.             ;
  2431.         if (*p == NUL)
  2432.             continue;
  2433.  
  2434.         /*
  2435.          * Skip this position if p_ek is not set and
  2436.          * typebuf[typeoff + offset] is an ESC and we are in insert mode
  2437.          */
  2438.         if (*tp == ESC && !p_ek && (State & INSERT))
  2439.             continue;
  2440.  
  2441.         len = typelen - offset;    /* length of the input */
  2442.         new_slen = 0;            /* Length of what will replace the termcode */
  2443.         key_name[0] = NUL;        /* no key name found yet */
  2444.  
  2445. #ifdef USE_GUI
  2446.         if (gui.in_use)
  2447.         {
  2448.             /*
  2449.              * GUI special key codes are all of the form [CSI xx].
  2450.              */
  2451.             if (*tp == CSI)            /* Special key from GUI */
  2452.             {
  2453.                 if (len < 3)
  2454.                     return -1;        /* Shouldn't happen */
  2455.                 slen = 3;
  2456.                 key_name[0] = tp[1];
  2457.                 key_name[1] = tp[2];
  2458.             }
  2459.         }
  2460.         else
  2461. #endif /* USE_GUI */
  2462.         {
  2463.             for (i = 0; i < tc_len; ++i)
  2464.             {
  2465.                 /*
  2466.                  * Ignore the entry if we are not at the start of typebuf[]
  2467.                  * and there are not enough characters to make a match.
  2468.                  */
  2469.                 slen = termcodes[i].len;
  2470.                 if (offset && len < slen)
  2471.                     continue;
  2472.                 if (STRNCMP(termcodes[i].code, tp,
  2473.                                      (size_t)(slen > len ? len : slen)) == 0)
  2474.                 {
  2475.                     if (len < slen)                /* got a partial sequence */
  2476.                         return -1;                /* need to get more chars */
  2477.  
  2478.                     key_name[0] = termcodes[i].name[0];
  2479.                     key_name[1] = termcodes[i].name[1];
  2480.  
  2481.                     /*
  2482.                      * If it's a shifted special key, then include the SHIFT
  2483.                      * modifier
  2484.                      */
  2485.                     if (unshift_special_key(&key_name[0]))
  2486.                     {
  2487.                         string[new_slen++] = K_SPECIAL;
  2488.                         string[new_slen++] = KS_MODIFIER;
  2489.                         string[new_slen++] = MOD_MASK_SHIFT;
  2490.                     }
  2491.                     break;
  2492.                 }
  2493.             }
  2494.         }
  2495.  
  2496.         if (key_name[0] == NUL)
  2497.             continue;        /* No match at this position, try next one */
  2498.  
  2499.         /* We only get here when we have a complete termcode match */
  2500.  
  2501. #ifdef USE_MOUSE
  2502.         /*
  2503.          * If it is a mouse click, get the coordinates.
  2504.          * we get "<t_mouse>scr", where
  2505.          *    s == encoded mouse button state (0x20 = left, 0x22 = right, etc)
  2506.          *    c == column + ' ' + 1 == column + 33
  2507.          *    r == row + ' ' + 1 == row + 33
  2508.          *
  2509.          * The coordinates are passed on through global variables. Ugly,
  2510.          * but this avoids trouble with mouse clicks at an unexpected
  2511.          * moment and allows for mapping them.
  2512.          */
  2513.         if (key_name[0] == KS_MOUSE)
  2514.         {
  2515.             num_bytes = get_bytes_from_buf(tp + slen, bytes, 3);
  2516.             if (num_bytes == -1)    /* not enough coordinates */
  2517.                 return -1;
  2518.             mouse_code = bytes[0];
  2519.             mouse_col = bytes[1] - ' ' - 1;
  2520.             mouse_row = bytes[2] - ' ' - 1;
  2521.             slen += num_bytes;
  2522.  
  2523.             /* Interpret the mouse code */
  2524.             is_click = is_drag = FALSE;
  2525.             current_button = (mouse_code & MOUSE_CLICK_MASK);
  2526.             if (current_button == MOUSE_RELEASE)
  2527.             {
  2528.                 /*
  2529.                  * If we get a mouse drag or release event when
  2530.                  * there is no mouse button held down (held_button ==
  2531.                  * MOUSE_RELEASE), produce a K_IGNORE below.
  2532.                  * (can happen when you hold down two buttons
  2533.                  * and then let them go, or click in the menu bar, but not
  2534.                  * on a menu, and drag into the text).
  2535.                  */
  2536.                 if ((mouse_code & MOUSE_DRAG) == MOUSE_DRAG)
  2537.                     is_drag = TRUE;
  2538.                 current_button = held_button;
  2539.             }
  2540.             else
  2541.             {
  2542. #if defined(UNIX) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
  2543. # ifdef USE_GUI
  2544.                 /*
  2545.                  * Only for Unix, when GUI is not active, we handle
  2546.                  * multi-clicks here.
  2547.                  */
  2548.                 if (!gui.in_use)
  2549. # endif
  2550.                 {
  2551.                     /*
  2552.                      * Compute the time elapsed since the previous mouse click.
  2553.                      */
  2554.                     gettimeofday(&mouse_time, NULL);
  2555.                     timediff = (mouse_time.tv_usec -
  2556.                                               orig_mouse_time.tv_usec) / 1000;
  2557.                     if (timediff < 0)
  2558.                         --orig_mouse_time.tv_sec;
  2559.                     timediff += (mouse_time.tv_sec -
  2560.                                                orig_mouse_time.tv_sec) * 1000;
  2561.                     orig_mouse_time = mouse_time;
  2562.                     if (mouse_code == orig_mouse_code &&
  2563.                             timediff < p_mouset &&
  2564.                             orig_num_clicks != 4 &&
  2565.                             orig_mouse_col == mouse_col &&
  2566.                             orig_mouse_row == mouse_row &&
  2567.                             orig_topline == curwin->w_topline)
  2568.                         ++orig_num_clicks;
  2569.                     else
  2570.                         orig_num_clicks = 1;
  2571.                     orig_mouse_col = mouse_col;
  2572.                     orig_mouse_row = mouse_row;
  2573.                     orig_topline = curwin->w_topline;
  2574.                 }
  2575. # ifdef USE_GUI
  2576.                 else
  2577.                     orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
  2578. # endif
  2579. #else
  2580.                 orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
  2581. #endif
  2582.                 is_click = TRUE;
  2583.                 orig_mouse_code = mouse_code;
  2584.             }
  2585.             if (!is_drag)
  2586.                 held_button = mouse_code & MOUSE_CLICK_MASK;
  2587.  
  2588.             /*
  2589.              * Translate the actual mouse event into a pseudo mouse event.
  2590.              * First work out what modifiers are to be used.
  2591.              */
  2592.             modifiers = 0x0;
  2593.             if (orig_mouse_code & MOUSE_SHIFT)
  2594.                 modifiers |= MOD_MASK_SHIFT;
  2595.             if (orig_mouse_code & MOUSE_CTRL)
  2596.                 modifiers |= MOD_MASK_CTRL;
  2597.             if (orig_mouse_code & MOUSE_ALT)
  2598.                 modifiers |= MOD_MASK_ALT;
  2599.             if (orig_num_clicks == 2)
  2600.                 modifiers |= MOD_MASK_2CLICK;
  2601.             else if (orig_num_clicks == 3)
  2602.                 modifiers |= MOD_MASK_3CLICK;
  2603.             else if (orig_num_clicks == 4)
  2604.                 modifiers |= MOD_MASK_4CLICK;
  2605.  
  2606.             /* Add the modifier codes to our string */
  2607.             if (modifiers != 0)
  2608.             {
  2609.                 string[new_slen++] = K_SPECIAL;
  2610.                 string[new_slen++] = KS_MODIFIER;
  2611.                 string[new_slen++] = modifiers;
  2612.             }
  2613.  
  2614.             /* Work out our pseudo mouse event */
  2615.             key_name[0] = KS_EXTRA;
  2616.             key_name[1] = get_pseudo_mouse_code(current_button,
  2617.                                                            is_click, is_drag);
  2618.         }
  2619. #endif /* USE_MOUSE */
  2620. #ifdef USE_GUI
  2621.         /*
  2622.          * If using the GUI, then we get menu and scrollbar events.
  2623.          * 
  2624.          * A menu event is encoded as K_SPECIAL, KS_MENU, K_FILLER followed by
  2625.          * four bytes which are to be taken as a pointer to the GuiMenu
  2626.          * structure.
  2627.          *
  2628.          * A scrollbar event is K_SPECIAL, KS_SCROLLBAR, K_FILLER followed by
  2629.          * one byte representing the scrollbar number, and then four bytes
  2630.          * representing a long_u which is the new value of the scrollbar.
  2631.          *
  2632.          * A horizontal scrollbar event is K_SPECIAL, KS_HORIZ_SCROLLBAR,
  2633.          * K_FILLER followed by four bytes representing a long_u which is the
  2634.          * new value of the scrollbar.
  2635.          */
  2636.         else if (key_name[0] == KS_MENU)
  2637.         {
  2638.             num_bytes = get_long_from_buf(tp + slen, &val);
  2639.             if (num_bytes == -1)
  2640.                 return -1;
  2641.             current_menu = (GuiMenu *)val;
  2642.             slen += num_bytes;
  2643.         }
  2644.         else if (key_name[0] == KS_SCROLLBAR)
  2645.         {
  2646.             num_bytes = get_bytes_from_buf(tp + slen, bytes, 1);
  2647.             if (num_bytes == -1)
  2648.                 return -1;
  2649.             current_scrollbar = (int)bytes[0];
  2650.             slen += num_bytes;
  2651.             num_bytes = get_long_from_buf(tp + slen, &val);
  2652.             if (num_bytes == -1)
  2653.                 return -1;
  2654.             scrollbar_value = val;
  2655.             slen += num_bytes;
  2656.         }
  2657.         else if (key_name[0] == KS_HORIZ_SCROLLBAR)
  2658.         {
  2659.             num_bytes = get_long_from_buf(tp + slen, &val);
  2660.             if (num_bytes == -1)
  2661.                 return -1;
  2662.             scrollbar_value = val;
  2663.             slen += num_bytes;
  2664.         }
  2665. #endif /* USE_GUI */
  2666.         /* Finally, add the special key code to our string */
  2667.         string[new_slen++] = K_SPECIAL;
  2668.         string[new_slen++] = key_name[0];
  2669.         string[new_slen++] = key_name[1];
  2670.         string[new_slen] = NUL;
  2671.         extra = new_slen - slen;
  2672.         if (extra < 0)
  2673.                 /* remove matched chars, taking care of noremap */
  2674.             del_typebuf(-extra, offset);
  2675.         else if (extra > 0)
  2676.                 /* insert the extra space we need */
  2677.             ins_typebuf(string + slen, FALSE, offset, FALSE);
  2678.  
  2679.         /*
  2680.          * Careful: del_typebuf() and ins_typebuf() may have
  2681.          * reallocated typebuf[]
  2682.          */
  2683.         vim_memmove(typebuf + typeoff + offset, string, (size_t)new_slen);
  2684.         return (len + extra + offset);
  2685.     }
  2686.     return 0;                        /* no match found */
  2687. }
  2688.  
  2689. /*
  2690.  * Replace any terminal code strings in from[] with the equivalent internal
  2691.  * vim representation.    This is used for the "from" and "to" part of a
  2692.  * mapping, and the "to" part of a menu command.
  2693.  * Any strings like "<C_UP>" are also replaced, unless 'cpoptions' contains
  2694.  * '<'.  Also unshifts shifted special keys.
  2695.  * K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL K_FILLER.
  2696.  *
  2697.  * The replacement is done in result[] and finally copied into allocated
  2698.  * memory. If this all works well *bufp is set to the allocated memory and a
  2699.  * pointer to it is returned. If something fails *bufp is set to NULL and from
  2700.  * is returned.
  2701.  *
  2702.  * CTRL-V characters are removed.  When "from_part" is TRUE, a trailing CTRL-V
  2703.  * is included, otherwise it is removed (for ":map xx ^V", maps xx to
  2704.  * nothing).  When 'cpoptions' does not contain 'B', a backslash can be used
  2705.  * instead of a CTRL-V.
  2706.  */
  2707.     char_u    *
  2708. replace_termcodes(from, bufp, from_part)
  2709.     char_u    *from;
  2710.     char_u    **bufp;
  2711.     int        from_part;
  2712. {
  2713.     int        i;
  2714.     char_u    key_name[2];
  2715.     char_u    *bp;
  2716.     char_u    *last_dash;
  2717.     char_u    *end_of_name;
  2718.     int        slen;
  2719.     int        modifiers;
  2720.     int        bit;
  2721.     int        key;
  2722.     int        dlen = 0;
  2723.     char_u    *src;
  2724.     int        do_backslash;        /* backslash is a special character */
  2725.     int        do_special;            /* recognize <> key codes */
  2726.     int        do_key_code;        /* recognize raw key codes */
  2727.     char_u    *result;            /* buffer for resulting string */
  2728.  
  2729.     do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
  2730.     do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL);
  2731.     do_key_code = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL);
  2732.  
  2733.     /*
  2734.      * Allocate space for the translation.  Worst case a single character is
  2735.      * replaced by 6 bytes (shifted special key), plus a NUL at the end.
  2736.      */
  2737.     result = alloc((unsigned)STRLEN(from) * 6 + 1);
  2738.     if (result == NULL)            /* out of memory */
  2739.     {
  2740.         *bufp = NULL;
  2741.         return from;
  2742.     }
  2743.  
  2744.     src = from;
  2745.  
  2746.     /*
  2747.      * Check for #n at start only: function key n
  2748.      */
  2749.     if (from_part && src[0] == '#' && isdigit(src[1]))        /* function key */
  2750.     {
  2751.         result[dlen++] = K_SPECIAL;
  2752.         result[dlen++] = 'k';
  2753.         if (src[1] == '0')
  2754.             result[dlen++] = ';';        /* #0 is F10 is "k;" */
  2755.         else
  2756.             result[dlen++] = src[1];    /* #3 is F3 is "k3" */
  2757.         src += 2;
  2758.     }
  2759.  
  2760.     /*
  2761.      * Copy each byte from *from to result[dlen]
  2762.      */
  2763.     while (*src != NUL)
  2764.     {
  2765.         /*
  2766.          * If 'cpoptions' does not contain '<', check for special key codes.
  2767.          */
  2768.         if (do_special)
  2769.         {
  2770.             /*
  2771.              * See if it's a string like "<C-S-MouseLeft>"
  2772.              */
  2773.             if (src[0] == '<')
  2774.             {
  2775.                 /* Find end of modifier list */
  2776.                 last_dash = src;
  2777.                 for (bp = src + 1; *bp == '-' || isidchar(*bp); bp++)
  2778.                 {
  2779.                     if (*bp == '-')
  2780.                     {
  2781.                         last_dash = bp;
  2782.                         if (bp[1] != NUL && bp[2] == '>')
  2783.                             ++bp;    /* anything accepted, like <C-?> */
  2784.                     }
  2785.                     if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
  2786.                         bp += 3;    /* skip t_xx, xx may be '-' or '>' */
  2787.                 }
  2788.  
  2789.                 if (*bp == '>')        /* found matching '>' */
  2790.                 {
  2791.                     end_of_name = bp + 1;
  2792.  
  2793.                     /* Which modifiers are given? */
  2794.                     modifiers = 0x0;
  2795.                     for (bp = src + 1; bp < last_dash; bp++)
  2796.                     {
  2797.                         if (*bp != '-')
  2798.                         {
  2799.                             bit = name_to_mod_mask(*bp);
  2800.                             if (bit == 0x0)
  2801.                                 break;        /* Illegal modifier name */
  2802.                             modifiers |= bit;
  2803.                         }
  2804.                     }
  2805.  
  2806.                     /*
  2807.                      * Legal modifier name.
  2808.                      */
  2809.                     if (bp >= last_dash)
  2810.                     {
  2811.                         /*
  2812.                          * Modifier with single letter
  2813.                          */
  2814.                         if (modifiers != 0 && last_dash[2] == '>')
  2815.                         {
  2816.                             key = last_dash[1];
  2817.                             if (modifiers & MOD_MASK_SHIFT)
  2818.                                 key = TO_UPPER(key);
  2819.                             if (modifiers & MOD_MASK_CTRL)
  2820.                                 key &= 0x1f;
  2821.                             if (modifiers & MOD_MASK_ALT)
  2822.                                 key |= 0x80;
  2823.                             src = end_of_name;
  2824.                             result[dlen++] = key;
  2825.                             continue;
  2826.                         }
  2827.  
  2828.                         /*
  2829.                          * Key name with or without modifier.
  2830.                          */
  2831.                         else if ((key = get_special_key_code(last_dash + 1))
  2832.                                                                          != 0)
  2833.                         {
  2834.                             /* Put the appropriate modifier in a string */
  2835.                             if (modifiers != 0)
  2836.                             {
  2837.                                 result[dlen++] = K_SPECIAL;
  2838.                                 result[dlen++] = KS_MODIFIER;
  2839.                                 result[dlen++] = modifiers;
  2840.                                 /*
  2841.                                  * Special trick: for <S-TAB>  K_TAB is used
  2842.                                  * instead of TAB (there are two keys for the
  2843.                                  * same thing).
  2844.                                  */
  2845.                                 if (key == TAB)
  2846.                                     key = K_TAB;
  2847.                             }
  2848.  
  2849.                             if (IS_SPECIAL(key))
  2850.                             {
  2851.                                 result[dlen++] = K_SPECIAL;
  2852.                                 result[dlen++] = KEY2TERMCAP0(key);
  2853.                                 result[dlen++] = KEY2TERMCAP1(key);
  2854.                             }
  2855.                             else
  2856.                                 result[dlen++] = key;        /* only modifiers */
  2857.                             src = end_of_name;
  2858.                             continue;
  2859.                         }
  2860.                     }
  2861.                 }
  2862.             }
  2863.         }
  2864.  
  2865.         /*
  2866.          * If 'cpoptions' does not contain 'k', see if it's an actual key-code.
  2867.          * Note that this is also checked after replacing the <> form.
  2868.          */
  2869.         if (do_key_code)
  2870.         {
  2871.             for (i = 0; i < tc_len; ++i)
  2872.             {
  2873.                 slen = termcodes[i].len;
  2874.                 if (STRNCMP(termcodes[i].code, src, (size_t)slen) == 0)
  2875.                 {
  2876.                     key_name[0] = termcodes[i].name[0];
  2877.                     key_name[1] = termcodes[i].name[1];
  2878.  
  2879.                     /*
  2880.                      * If it's a shifted special key, then include the SHIFT
  2881.                      * modifier
  2882.                      */
  2883.                     if (unshift_special_key(&key_name[0]))
  2884.                     {
  2885.                         result[dlen++] = K_SPECIAL;
  2886.                         result[dlen++] = KS_MODIFIER;
  2887.                         result[dlen++] = MOD_MASK_SHIFT;
  2888.                     }
  2889.                     result[dlen++] = K_SPECIAL;
  2890.                     result[dlen++] = key_name[0];
  2891.                     result[dlen++] = key_name[1];
  2892.                     src += slen;
  2893.                     break;
  2894.                 }
  2895.             }
  2896.  
  2897.             /*
  2898.              * If terminal code matched, continue after it.
  2899.              * If no terminal code matched and the character is K_SPECIAL,
  2900.              * replace it with K_SPECIAL KS_SPECIAL K_FILLER
  2901.              */
  2902.             if (i != tc_len)
  2903.                 continue;
  2904.         }
  2905.  
  2906.         if (*src == K_SPECIAL)
  2907.         {
  2908.             result[dlen++] = K_SPECIAL;
  2909.             result[dlen++] = KS_SPECIAL;
  2910.             result[dlen++] = K_FILLER;
  2911.             ++src;
  2912.             continue;
  2913.         }
  2914.  
  2915.         /*
  2916.          * Remove CTRL-V and ignore the next character.
  2917.          * For "from" side the CTRL-V at the end is included, for the "to"
  2918.          * part it is removed.
  2919.          * If 'cpoptions' does not contain 'B', also accept a backslash.
  2920.          */
  2921.         key = *src;
  2922.         if (key == Ctrl('V') || (do_backslash && key == '\\'))
  2923.         {
  2924.             ++src;                                /* skip CTRL-V or backslash */
  2925.             if (*src == NUL)
  2926.             {
  2927.                 if (from_part)
  2928.                     result[dlen++] = key;
  2929.                 break;
  2930.             }
  2931.         }
  2932.         result[dlen++] = *src++;
  2933.     }
  2934.     result[dlen] = NUL;
  2935.  
  2936.     /*
  2937.      * Copy the new string to allocated memory.
  2938.      * If this fails, just return from.
  2939.      */
  2940.     if ((*bufp = strsave(result)) != NULL)
  2941.         from = *bufp;
  2942.     vim_free(result);
  2943.     return from;
  2944. }
  2945.  
  2946. /*
  2947.  * Gather the first characters in the terminal key codes into a string.
  2948.  * Used to speed up check_termcode().
  2949.  */
  2950.     static void
  2951. gather_termleader()
  2952. {
  2953.     int        i;
  2954.     int        len = 0;
  2955.  
  2956. #ifdef USE_GUI
  2957.     if (gui.in_use)
  2958.         termleader[len++] = CSI;    /* the GUI codes are not in termcodes[] */
  2959. #endif
  2960.     termleader[len] = NUL;
  2961.  
  2962.     for (i = 0; i < tc_len; ++i)
  2963.         if (vim_strchr(termleader, termcodes[i].code[0]) == NULL)
  2964.         {
  2965.             termleader[len++] = termcodes[i].code[0];
  2966.             termleader[len] = NUL;
  2967.         }
  2968.  
  2969.     need_gather = FALSE;
  2970. }
  2971.  
  2972. /*
  2973.  * Show all termcodes (for ":set termcap")
  2974.  * This code looks a lot like showoptions(), but is different.
  2975.  */
  2976.     void
  2977. show_termcodes()
  2978. {
  2979.     int                col;
  2980.     int                *items;
  2981.     int                item_count;
  2982.     int                run;
  2983.     int                row, rows;
  2984.     int                cols;
  2985.     int                i;
  2986.     int                len;
  2987.  
  2988. #define INC    27        /* try to make three columns */
  2989. #define GAP 2        /* spaces between columns */
  2990.  
  2991.     if (tc_len == 0)        /* no terminal codes (must be GUI) */
  2992.         return;
  2993.     items = (int *)alloc((unsigned)(sizeof(int) * tc_len));
  2994.     if (items == NULL)
  2995.         return;
  2996.  
  2997.     set_highlight('t');        /* Highlight title */
  2998.     start_highlight();
  2999.     MSG_OUTSTR("\n--- Terminal keys ---");
  3000.     stop_highlight();
  3001.  
  3002.     /*
  3003.      * do the loop two times:
  3004.      * 1. display the short items (non-strings and short strings)
  3005.      * 2. display the long items (strings)
  3006.      */
  3007.     for (run = 1; run <= 2 && !got_int; ++run)
  3008.     {
  3009.         /*
  3010.          * collect the items in items[]
  3011.          */
  3012.         item_count = 0;
  3013.         for (i = 0; i < tc_len; i++)
  3014.         {
  3015.             len = show_one_termcode(termcodes[i].name,
  3016.                                                     termcodes[i].code, FALSE);
  3017.             if ((len <= INC - GAP && run == 1) || (len > INC - GAP && run == 2))
  3018.                 items[item_count++] = i;
  3019.         }
  3020.  
  3021.         /*
  3022.          * display the items
  3023.          */
  3024.         if (run == 1)
  3025.         {
  3026.             cols = (Columns + GAP) / INC;
  3027.             if (cols == 0)
  3028.                 cols = 1;
  3029.             rows = (item_count + cols - 1) / cols;
  3030.         }
  3031.         else    /* run == 2 */
  3032.             rows = item_count;
  3033.         for (row = 0; row < rows && !got_int; ++row)
  3034.         {
  3035.             msg_outchar('\n');                        /* go to next line */
  3036.             if (got_int)                            /* 'q' typed in more */
  3037.                 break;
  3038.             col = 0;
  3039.             for (i = row; i < item_count; i += rows)
  3040.             {
  3041.                 msg_pos(-1, col);                    /* make columns */
  3042.                 show_one_termcode(termcodes[items[i]].name,
  3043.                                               termcodes[items[i]].code, TRUE);
  3044.                 col += INC;
  3045.             }
  3046.             flushbuf();
  3047.             mch_breakcheck();
  3048.         }
  3049.     }
  3050.     vim_free(items);
  3051. }
  3052.  
  3053. /*
  3054.  * Show one termcode entry.
  3055.  * Output goes into IObuff[]
  3056.  */
  3057.     int
  3058. show_one_termcode(name, code, printit)
  3059.     char_u    *name;
  3060.     char_u    *code;
  3061.     int        printit;
  3062. {
  3063.     char_u        *p;
  3064.     int            len;
  3065.  
  3066.     if (name[0] > '~')
  3067.     {
  3068.         IObuff[0] = ' ';
  3069.         IObuff[1] = ' ';
  3070.         IObuff[2] = ' ';
  3071.         IObuff[3] = ' ';
  3072.     }
  3073.     else
  3074.     {
  3075.         IObuff[0] = 't';
  3076.         IObuff[1] = '_';
  3077.         IObuff[2] = name[0];
  3078.         IObuff[3] = name[1];
  3079.     }
  3080.     IObuff[4] = ' ';
  3081.  
  3082.     p = get_special_key_name(TERMCAP2KEY(name[0], name[1]), 0);
  3083.     if (p[1] != 't')
  3084.         STRCPY(IObuff + 5, p);
  3085.     else
  3086.         IObuff[5] = NUL;
  3087.     len = STRLEN(IObuff);
  3088.     do
  3089.         IObuff[len++] = ' ';
  3090.     while (len < 17);
  3091.     IObuff[len] = NUL;
  3092.     if (code == NULL)
  3093.         len += 4;
  3094.     else
  3095.         len += strsize(code);
  3096.  
  3097.     if (printit)
  3098.     {
  3099.         msg_outstr(IObuff);
  3100.         if (code == NULL)
  3101.             msg_outstr((char_u *)"NULL");
  3102.         else
  3103.             msg_outtrans(code);
  3104.     }
  3105.     return len;
  3106. }
  3107.